You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by cl...@apache.org on 2023/01/13 20:52:33 UTC

[activemq-artemis] branch main updated: ARTEMIS-3875 - adding consumer and producer metrics

This is an automated email from the ASF dual-hosted git repository.

clebertsuconic pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git


The following commit(s) were added to refs/heads/main by this push:
     new b02002fc66 ARTEMIS-3875 - adding consumer and producer metrics
     new 56111ebfef This closes #4183
b02002fc66 is described below

commit b02002fc6645c5fcde9019a053f4575ab273df4d
Author: Andy Taylor <an...@gmail.com>
AuthorDate: Tue Jun 28 10:03:57 2022 +0100

    ARTEMIS-3875 - adding consumer and producer metrics
    
    https://issues.apache.org/jira/browse/ARTEMIS-3875
---
 .../core/client/impl/ClientProducerImpl.java       |   22 +-
 .../core/client/impl/ClientProducerInternal.java   |    2 +
 .../core/client/impl/ClientSessionImpl.java        |   14 +-
 .../core/protocol/core/CoreRemotingConnection.java |    5 +
 .../protocol/core/impl/ActiveMQSessionContext.java |   38 +-
 .../core/protocol/core/impl/PacketDecoder.java     |    5 +-
 .../core/protocol/core/impl/PacketImpl.java        |    5 +
 .../impl/wireformat/CreateProducerMessage.java     |   83 +
 .../impl/wireformat/RemoveProducerMessage.java     |   68 +
 .../wireformat/SessionSendContinuationMessage.java |    4 +
 .../SessionSendContinuationMessage_V3.java         |   72 +
 .../core/impl/wireformat/SessionSendMessage.java   |    3 +
 .../impl/wireformat/SessionSendMessage_V3.java     |   63 +
 .../artemis/spi/core/remoting/SessionContext.java  |   10 +-
 .../src/main/resources/activemq-version.properties |    2 +-
 .../main/webapp/plugin/js/components/consumers.js  |   47 +-
 .../main/webapp/plugin/js/components/producers.js  |   13 +-
 .../protocol/amqp/broker/AMQPSessionCallback.java  |   11 +-
 .../protocol/amqp/proton/AMQPSessionContext.java   |    9 +-
 .../amqp/proton/ProtonServerReceiverContext.java   |    1 +
 .../core/protocol/mqtt/MQTTConnectionManager.java  |    4 +-
 .../core/protocol/mqtt/MQTTPublishManager.java     |   15 +-
 .../core/protocol/openwire/OpenWireConnection.java |    7 +-
 .../core/protocol/openwire/amq/AMQConsumer.java    |    1 +
 .../core/protocol/openwire/amq/AMQSession.java     |    7 +-
 .../openwire/amq/OpenWireConnectionTest.java       |    2 +-
 .../core/protocol/stomp/StompProtocolManager.java  |    2 +-
 .../artemis/core/protocol/stomp/StompSession.java  |   19 +-
 .../core/management/impl/AbstractControl.java      |    4 +-
 .../management/impl/ActiveMQServerControlImpl.java |   31 +-
 .../core/management/impl/QueueControlImpl.java     |   18 +-
 .../core/management/impl/view/ConsumerField.java   |   34 +-
 .../core/management/impl/view/ConsumerView.java    |   29 +-
 .../core/management/impl/view/ProducerField.java   |   26 +-
 .../core/management/impl/view/ProducerView.java    |    6 +-
 .../view/predicate/ConsumerFilterPredicate.java    |   12 +
 .../artemis/core/protocol/ServerPacketDecoder.java |   17 +-
 .../protocol/core/ServerSessionPacketHandler.java  |   43 +-
 .../protocol/core/impl/ActiveMQPacketHandler.java  |    7 +-
 .../artemis/core/server/ActiveMQServer.java        |    7 +-
 .../artemis/core/server/ActiveMQServerLogger.java  |    4 +
 .../activemq/artemis/core/server/ConsumerInfo.java |   47 +
 .../artemis/core/server/ServerConsumer.java        |    7 +
 .../artemis/core/server/ServerProducer.java        |   16 +-
 .../artemis/core/server/ServerSession.java         |   16 +-
 .../core/server/impl/ActiveMQServerImpl.java       |   15 +-
 .../core/server/impl/ServerConsumerImpl.java       |  174 +-
 .../server/impl/ServerLegacyProducersImpl.java     |   83 +
 .../core/server/impl/ServerProducerImpl.java       |   59 +-
 .../impl/ServerProducers.java}                     |   25 +-
 .../core/server/impl/ServerProducersImpl.java      |   63 +
 .../core/server/impl/ServerSessionImpl.java        |  125 +-
 .../transaction/TransactionPropertyIndexes.java    |    2 +
 .../core/transaction/impl/TransactionImpl.java     |    2 +-
 .../artemis/tests/util/ActiveMQTestBase.java       |   11 +
 pom.xml                                            |    2 +-
 .../tests/integration/cli/DummyServerConsumer.java |   45 +
 .../tests/integration/client/HangConsumerTest.java |    5 +-
 .../tests/integration/client/LargeMessageTest.java |   75 +
 .../jms/client/TemporaryDestinationTest.java       |   22 +-
 .../management/ActiveMQServerControlTest.java      | 3447 ++++++++++++++------
 .../ActiveMQServerControlUsingCoreTest.java        |    1 +
 .../integration/management/QueueControlTest.java   |  452 ++-
 .../artemis/tests/integration/mqtt/MQTTTest.java   |   61 +
 .../artemis/tests/integration/stomp/StompTest.java |   42 +
 65 files changed, 4407 insertions(+), 1162 deletions(-)

diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientProducerImpl.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientProducerImpl.java
index c9c6d75926..f3fd2e1f69 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientProducerImpl.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientProducerImpl.java
@@ -44,6 +44,8 @@ public class ClientProducerImpl implements ClientProducerInternal {
 
    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
+   private final int id;
+
    private final SimpleString address;
 
    private final ClientSessionInternal session;
@@ -75,7 +77,10 @@ public class ClientProducerImpl implements ClientProducerInternal {
                              final boolean autoGroup,
                              final SimpleString groupID,
                              final int minLargeMessageSize,
-                             final SessionContext sessionContext) {
+                             final SessionContext sessionContext,
+                             final int producerID) {
+      this.id = producerID;
+
       this.sessionContext = sessionContext;
 
       this.session = session;
@@ -197,6 +202,11 @@ public class ClientProducerImpl implements ClientProducerInternal {
       return producerCredits;
    }
 
+   @Override
+   public int getID() {
+      return id;
+   }
+
    private void doCleanup() {
       if (address != null) {
          session.returnCredits(address);
@@ -204,6 +214,8 @@ public class ClientProducerImpl implements ClientProducerInternal {
 
       session.removeProducer(this);
 
+      sessionContext.removeProducer(id);
+
       closed = true;
    }
 
@@ -290,7 +302,7 @@ public class ClientProducerImpl implements ClientProducerInternal {
 
       theCredits.acquireCredits(creditSize);
 
-      sessionContext.sendFullMessage(msgI, sendBlocking, handler, address);
+      sessionContext.sendFullMessage(msgI, sendBlocking, handler, address, id);
    }
 
    private void checkClosed() throws ActiveMQException {
@@ -381,7 +393,7 @@ public class ClientProducerImpl implements ClientProducerInternal {
             lastChunk = pos >= bodySize;
             SendAcknowledgementHandler messageHandler = lastChunk ? handler : null;
 
-            int creditsUsed = sessionContext.sendServerLargeMessageChunk(msgI, -1, sendBlocking, lastChunk, bodyBuffer.array(), messageHandler);
+            int creditsUsed = sessionContext.sendServerLargeMessageChunk(msgI, -1, sendBlocking, lastChunk, bodyBuffer.array(), id, messageHandler);
 
             credits.acquireCredits(creditsUsed);
          }
@@ -492,7 +504,7 @@ public class ClientProducerImpl implements ClientProducerInternal {
                      headerSent = true;
                      sendInitialLargeMessageHeader(msgI, credits);
                   }
-                  int creditsSent = sessionContext.sendLargeMessageChunk(msgI, messageSize.get(), sendBlocking, true, buff, reconnectID, handler);
+                  int creditsSent = sessionContext.sendLargeMessageChunk(msgI, messageSize.get(), sendBlocking, true, buff, reconnectID, id, handler);
                   credits.acquireCredits(creditsSent);
                }
             } else {
@@ -501,7 +513,7 @@ public class ClientProducerImpl implements ClientProducerInternal {
                   sendInitialLargeMessageHeader(msgI, credits);
                }
 
-               int creditsSent = sessionContext.sendLargeMessageChunk(msgI, messageSize.get(), sendBlocking, false, buff, reconnectID, handler);
+               int creditsSent = sessionContext.sendLargeMessageChunk(msgI, messageSize.get(), sendBlocking, false, buff, reconnectID, id, handler);
                credits.acquireCredits(creditsSent);
             }
          }
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientProducerInternal.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientProducerInternal.java
index 6190885e3d..963f86fdbe 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientProducerInternal.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientProducerInternal.java
@@ -26,4 +26,6 @@ public interface ClientProducerInternal extends ClientProducer {
    void cleanUp();
 
    ClientProducerCredits getProducerCredits();
+
+   int getID();
 }
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientSessionImpl.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientSessionImpl.java
index dfb99e65ee..e388673645 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientSessionImpl.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/client/impl/ClientSessionImpl.java
@@ -161,6 +161,8 @@ public final class ClientSessionImpl implements ClientSessionInternal, FailureLi
 
    private final CoreMessageObjectPools coreMessageObjectPools = new CoreMessageObjectPools();
 
+   private AtomicInteger producerIDs = new AtomicInteger();
+
    ClientSessionImpl(final ClientSessionFactoryInternal sessionFactory,
                      final String name,
                      final String username,
@@ -2031,10 +2033,20 @@ public final class ClientSessionImpl implements ClientSessionInternal, FailureLi
                                                  final int maxRate) throws ActiveMQException {
       checkClosed();
 
-      ClientProducerInternal producer = new ClientProducerImpl(this, address, maxRate == -1 ? null : new TokenBucketLimiterImpl(maxRate, false), autoCommitSends && blockOnNonDurableSend, autoCommitSends && blockOnDurableSend, autoGroup, groupID == null ? null : new SimpleString(groupID), minLargeMessageSize, sessionContext);
+      ClientProducerInternal producer = new ClientProducerImpl(this,
+                                                                      address,
+                                                                      maxRate == -1 ? null : new TokenBucketLimiterImpl(maxRate, false),
+                                                                      autoCommitSends && blockOnNonDurableSend,
+                                                                      autoCommitSends && blockOnDurableSend,
+                                                                      autoGroup, groupID == null ? null : new SimpleString(groupID),
+                                                                      minLargeMessageSize,
+                                                                      sessionContext,
+                                                                      producerIDs.incrementAndGet());
 
       addProducer(producer);
 
+      sessionContext.createProducer(producer);
+
       return producer;
    }
 
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/CoreRemotingConnection.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/CoreRemotingConnection.java
index 43035b0520..3f8699b5b8 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/CoreRemotingConnection.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/CoreRemotingConnection.java
@@ -76,6 +76,11 @@ public interface CoreRemotingConnection extends RemotingConnection {
       return  version < PacketImpl.ARTEMIS_2_18_0_VERSION;
    }
 
+   default boolean isBeforeProducerMetricsChanged() {
+      int version = getChannelVersion();
+      return version < PacketImpl.ARTEMIS_2_28_0_VERSION;
+   }
+
    /**
     * Sets the client protocol used on the communication. This will determine if the client has
     * support for certain packet types
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/ActiveMQSessionContext.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/ActiveMQSessionContext.java
index 7f248b7403..b864dc1013 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/ActiveMQSessionContext.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/ActiveMQSessionContext.java
@@ -58,6 +58,7 @@ import org.apache.activemq.artemis.core.client.impl.ClientConsumerInternal;
 import org.apache.activemq.artemis.core.client.impl.ClientLargeMessageInternal;
 import org.apache.activemq.artemis.core.client.impl.ClientMessageInternal;
 import org.apache.activemq.artemis.core.client.impl.ClientProducerCredits;
+import org.apache.activemq.artemis.core.client.impl.ClientProducerInternal;
 import org.apache.activemq.artemis.core.client.impl.ClientSessionImpl;
 import org.apache.activemq.artemis.core.message.impl.CoreMessage;
 import org.apache.activemq.artemis.core.protocol.core.Channel;
@@ -68,6 +69,7 @@ import org.apache.activemq.artemis.core.protocol.core.Packet;
 import org.apache.activemq.artemis.core.protocol.core.ResponseHandler;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ActiveMQExceptionMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.CreateAddressMessage;
+import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.CreateProducerMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.CreateQueueMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.CreateQueueMessage_V2;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.CreateSessionMessage;
@@ -76,6 +78,7 @@ import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.Disconnect
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.DisconnectConsumerWithKillMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ReattachSessionMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ReattachSessionResponseMessage;
+import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.RemoveProducerMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.RollbackMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionAcknowledgeMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionAddMetaDataMessageV2;
@@ -105,10 +108,12 @@ import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionRec
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionRequestProducerCreditsMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendContinuationMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendContinuationMessage_V2;
+import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendContinuationMessage_V3;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendLargeMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendMessage_1X;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendMessage_V2;
+import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendMessage_V3;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionUniqueAddMetaDataMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionXAAfterFailedMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionXACommitMessage;
@@ -371,6 +376,20 @@ public class ActiveMQSessionContext extends SessionContext {
       return remotingConnection.isWritable(callback);
    }
 
+   @Override
+   public void createProducer(ClientProducerInternal producer) {
+      if (!sessionChannel.getConnection().isBeforeProducerMetricsChanged()) {
+         sessionChannel.send(new CreateProducerMessage(producer.getID(), producer.getAddress()));
+      }
+   }
+
+   @Override
+   public void removeProducer(int id) {
+      if (!sessionChannel.getConnection().isBeforeProducerMetricsChanged()) {
+         sessionChannel.send(new RemoveProducerMessage(id));
+      }
+   }
+
    @Override
    public ClientConsumerInternal createConsumer(SimpleString queueName,
                                                 SimpleString filterString,
@@ -546,15 +565,19 @@ public class ActiveMQSessionContext extends SessionContext {
    public void sendFullMessage(ICoreMessage msgI,
                                boolean sendBlocking,
                                SendAcknowledgementHandler handler,
-                               SimpleString defaultAddress) throws ActiveMQException {
+                               SimpleString defaultAddress,
+                               int senderID) throws ActiveMQException {
       final SessionSendMessage packet;
       if (sessionChannel.getConnection().isVersionBeforeAddressChange()) {
          packet = new SessionSendMessage_1X(msgI, sendBlocking, handler);
       } else if (sessionChannel.getConnection().isVersionBeforeAsyncResponseChange()) {
          packet = new SessionSendMessage(msgI, sendBlocking, handler);
-      } else {
+      } else if (sessionChannel.getConnection().isBeforeProducerMetricsChanged()) {
          boolean responseRequired = confirmationWindow != -1 || sendBlocking;
          packet = new SessionSendMessage_V2(msgI, responseRequired, handler);
+      } else {
+         boolean responseRequired = confirmationWindow != -1 || sendBlocking;
+         packet = new SessionSendMessage_V3(msgI, responseRequired, handler, senderID);
       }
       if (sendBlocking) {
          sessionChannel.sendBlocking(packet, PacketImpl.NULL_RESPONSE);
@@ -579,8 +602,9 @@ public class ActiveMQSessionContext extends SessionContext {
                                     boolean lastChunk,
                                     byte[] chunk,
                                     int reconnectID,
+                                    int senderID,
                                     SendAcknowledgementHandler messageHandler) throws ActiveMQException {
-      return sendSessionSendContinuationMessage(this.sessionChannel, msgI, messageBodySize, sendBlocking, lastChunk, chunk, messageHandler);
+      return sendSessionSendContinuationMessage(this.sessionChannel, msgI, messageBodySize, sendBlocking, lastChunk, chunk, senderID,  messageHandler);
    }
 
    @Override
@@ -589,8 +613,9 @@ public class ActiveMQSessionContext extends SessionContext {
                                           boolean sendBlocking,
                                           boolean lastChunk,
                                           byte[] chunk,
+                                          int senderID,
                                           SendAcknowledgementHandler messageHandler) throws ActiveMQException {
-      return sendSessionSendContinuationMessage(this.sessionChannel, msgI, messageBodySize, sendBlocking, lastChunk, chunk, messageHandler);
+      return sendSessionSendContinuationMessage(this.sessionChannel, msgI, messageBodySize, sendBlocking, lastChunk, chunk, senderID, messageHandler);
    }
 
    @Override
@@ -1043,13 +1068,16 @@ public class ActiveMQSessionContext extends SessionContext {
                                                          boolean sendBlocking,
                                                          boolean lastChunk,
                                                          byte[] chunk,
+                                                         int senderID,
                                                          SendAcknowledgementHandler messageHandler) throws ActiveMQException {
       final boolean requiresResponse = lastChunk && sendBlocking;
       final SessionSendContinuationMessage chunkPacket;
       if (sessionChannel.getConnection().isVersionBeforeAsyncResponseChange()) {
          chunkPacket = new SessionSendContinuationMessage(msgI, chunk, !lastChunk, requiresResponse, messageBodySize, messageHandler);
-      } else {
+      } else if (sessionChannel.getConnection().isBeforeProducerMetricsChanged()) {
          chunkPacket = new SessionSendContinuationMessage_V2(msgI, chunk, !lastChunk, requiresResponse || confirmationWindow != -1, messageBodySize, messageHandler);
+      } else {
+         chunkPacket = new SessionSendContinuationMessage_V3(msgI, chunk, !lastChunk, requiresResponse || confirmationWindow != -1, messageBodySize, senderID, messageHandler);
       }
       //perform a weak form of flow control to avoid OOM on tight loops
       final CoreRemotingConnection connection = channel.getConnection();
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/PacketDecoder.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/PacketDecoder.java
index 2967c970e9..6b71951cd3 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/PacketDecoder.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/PacketDecoder.java
@@ -79,6 +79,7 @@ import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionRec
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionRequestProducerCreditsMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendContinuationMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendContinuationMessage_V2;
+import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendContinuationMessage_V3;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionUniqueAddMetaDataMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionXAAfterFailedMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionXACommitMessage;
@@ -423,8 +424,10 @@ public abstract class PacketDecoder implements Serializable {
          case SESS_SEND_CONTINUATION: {
             if (connection.isVersionBeforeAsyncResponseChange()) {
                packet = new SessionSendContinuationMessage();
-            } else {
+            } else if (connection.isBeforeProducerMetricsChanged()) {
                packet = new SessionSendContinuationMessage_V2();
+            } else {
+               packet = new SessionSendContinuationMessage_V3();
             }
             break;
          }
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/PacketImpl.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/PacketImpl.java
index b83e3ee849..00020faecc 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/PacketImpl.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/PacketImpl.java
@@ -47,6 +47,9 @@ public class PacketImpl implements Packet {
    // 2.24.0
    public static final int ARTEMIS_2_24_0_VERSION = 133;
 
+   // 2.28.0
+   public static final int ARTEMIS_2_28_0_VERSION = 134;
+
    public static final SimpleString OLD_QUEUE_PREFIX = new SimpleString("jms.queue.");
    public static final SimpleString OLD_TEMP_QUEUE_PREFIX = new SimpleString("jms.tempqueue.");
    public static final SimpleString OLD_TOPIC_PREFIX = new SimpleString("jms.topic.");
@@ -293,7 +296,9 @@ public class PacketImpl implements Packet {
 
    public static final byte DISCONNECT_V3 = -19;
 
+   public static final byte CREATE_PRODUCER = -20;
 
+   public static final byte REMOVE_PRODUCER = -21;
 
    public PacketImpl(final byte type) {
       this.type = type;
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/CreateProducerMessage.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/CreateProducerMessage.java
new file mode 100644
index 0000000000..ead9a9594b
--- /dev/null
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/CreateProducerMessage.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.core.protocol.core.impl.wireformat;
+
+import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
+import org.apache.activemq.artemis.api.core.SimpleString;
+import org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl;
+
+import java.util.Objects;
+
+public class CreateProducerMessage  extends PacketImpl {
+   protected int id;
+
+   protected SimpleString address;
+
+   public CreateProducerMessage() {
+      super(PacketImpl.CREATE_PRODUCER);
+   }
+
+   public CreateProducerMessage(int id, SimpleString address) {
+      super(PacketImpl.CREATE_PRODUCER);
+      this.id = id;
+      this.address = address;
+   }
+
+   public int getId() {
+      return id;
+   }
+
+   public void setId(int id) {
+      this.id = id;
+   }
+
+   public SimpleString getAddress() {
+      return address;
+   }
+
+   public void setAddress(SimpleString address) {
+      this.address = address;
+   }
+
+
+
+   @Override
+   public void encodeRest(final ActiveMQBuffer buffer) {
+      buffer.writeInt(id);
+      buffer.writeNullableSimpleString(address);
+   }
+
+   @Override
+   public void decodeRest(final ActiveMQBuffer buffer) {
+      id = buffer.readInt();
+      address = buffer.readNullableSimpleString();
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+      if (!super.equals(o)) return false;
+      CreateProducerMessage that = (CreateProducerMessage) o;
+      return Objects.equals(id, that.id) && Objects.equals(address, that.address);
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hash(super.hashCode(), id, address);
+   }
+}
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/RemoveProducerMessage.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/RemoveProducerMessage.java
new file mode 100644
index 0000000000..a6f8d7755c
--- /dev/null
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/RemoveProducerMessage.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.core.protocol.core.impl.wireformat;
+
+import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
+import org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl;
+
+import java.util.Objects;
+
+public class RemoveProducerMessage extends PacketImpl {
+
+   protected int id;
+
+   public RemoveProducerMessage(int id) {
+      super(PacketImpl.REMOVE_PRODUCER);
+      this.id = id;
+   }
+
+   public RemoveProducerMessage() {
+      super(PacketImpl.REMOVE_PRODUCER);
+   }
+
+   public int getId() {
+      return id;
+   }
+
+   public void setId(int id) {
+      this.id = id;
+   }
+
+   @Override
+   public void encodeRest(final ActiveMQBuffer buffer) {
+      buffer.writeInt(id);
+   }
+
+   @Override
+   public void decodeRest(final ActiveMQBuffer buffer) {
+      id = buffer.readInt();
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o) return true;
+      if (o == null || getClass() != o.getClass()) return false;
+      if (!super.equals(o)) return false;
+      RemoveProducerMessage that = (RemoveProducerMessage) o;
+      return Objects.equals(id, that.id);
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hash(super.hashCode(), id);
+   }
+}
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendContinuationMessage.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendContinuationMessage.java
index 1aa521650e..1db5ff7f47 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendContinuationMessage.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendContinuationMessage.java
@@ -180,4 +180,8 @@ public class SessionSendContinuationMessage extends SessionContinuationMessage {
    public SendAcknowledgementHandler getHandler() {
       return handler;
    }
+
+   public int getSenderID() {
+      return -1;
+   }
 }
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendContinuationMessage_V3.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendContinuationMessage_V3.java
new file mode 100644
index 0000000000..60db0c2d92
--- /dev/null
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendContinuationMessage_V3.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.core.protocol.core.impl.wireformat;
+
+import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
+import org.apache.activemq.artemis.api.core.Message;
+import org.apache.activemq.artemis.api.core.client.SendAcknowledgementHandler;
+import org.apache.activemq.artemis.utils.DataConstants;
+
+/**
+ * A SessionSendContinuationMessage<br>
+ */
+public class SessionSendContinuationMessage_V3 extends SessionSendContinuationMessage_V2 {
+
+   private int senderID;
+
+   public SessionSendContinuationMessage_V3() {
+      super();
+   }
+
+   /**
+    * @param body
+    * @param continues
+    * @param requiresResponse
+    */
+   public SessionSendContinuationMessage_V3(final Message message,
+                                            final byte[] body,
+                                            final boolean continues,
+                                            final boolean requiresResponse,
+                                            final long messageBodySize,
+                                            final int senderID,
+                                            final SendAcknowledgementHandler handler) {
+      super(message, body, continues, requiresResponse, messageBodySize, handler);
+      this.senderID = senderID;
+   }
+
+   @Override
+   public int expectedEncodeSize() {
+      return super.expectedEncodeSize() + DataConstants.SIZE_INT;
+   }
+
+   @Override
+   public void encodeRest(final ActiveMQBuffer buffer) {
+      super.encodeRest(buffer);
+      buffer.writeInt(senderID);
+   }
+
+   @Override
+   public void decodeRest(final ActiveMQBuffer buffer) {
+      super.decodeRest(buffer);
+      senderID = buffer.readInt();
+   }
+
+   @Override
+   public int getSenderID() {
+      return senderID;
+   }
+}
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendMessage.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendMessage.java
index dafcb8fc6d..206af04c77 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendMessage.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendMessage.java
@@ -136,4 +136,7 @@ public class SessionSendMessage extends MessagePacket {
       return true;
    }
 
+   public int getSenderID() {
+      return -1;
+   }
 }
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendMessage_V3.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendMessage_V3.java
new file mode 100644
index 0000000000..690b931f62
--- /dev/null
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/wireformat/SessionSendMessage_V3.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.core.protocol.core.impl.wireformat;
+
+import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
+import org.apache.activemq.artemis.api.core.ICoreMessage;
+import org.apache.activemq.artemis.api.core.client.SendAcknowledgementHandler;
+import org.apache.activemq.artemis.core.message.impl.CoreMessage;
+import org.apache.activemq.artemis.utils.DataConstants;
+
+public class SessionSendMessage_V3 extends SessionSendMessage_V2 {
+
+   private int senderID;
+
+   /** This will be using the CoreMessage because it is meant for the core-protocol */
+   public SessionSendMessage_V3(final ICoreMessage message,
+                                final boolean requiresResponse,
+                                final SendAcknowledgementHandler handler,
+                                final int senderID) {
+      super(message, requiresResponse, handler);
+      this.senderID = senderID;
+   }
+
+   public SessionSendMessage_V3(final CoreMessage message) {
+      super(message);
+   }
+
+   @Override
+   public void encodeRest(ActiveMQBuffer buffer) {
+      super.encodeRest(buffer);
+      buffer.writeInt(senderID);
+   }
+
+   @Override
+   public void decodeRest(final ActiveMQBuffer buffer) {
+      super.decodeRest(buffer);
+      senderID = buffer.readInt();
+   }
+
+   @Override
+   protected int fieldsEncodeSize() {
+      return super.fieldsEncodeSize() + DataConstants.SIZE_INT;
+   }
+
+   @Override
+   public int getSenderID() {
+      return senderID;
+   }
+}
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/remoting/SessionContext.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/remoting/SessionContext.java
index cbe9dd8b54..7c33fff290 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/remoting/SessionContext.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/remoting/SessionContext.java
@@ -37,6 +37,7 @@ import org.apache.activemq.artemis.core.client.impl.ClientConsumerInternal;
 import org.apache.activemq.artemis.core.client.impl.ClientLargeMessageInternal;
 import org.apache.activemq.artemis.core.client.impl.ClientMessageInternal;
 import org.apache.activemq.artemis.core.client.impl.ClientProducerCredits;
+import org.apache.activemq.artemis.core.client.impl.ClientProducerInternal;
 import org.apache.activemq.artemis.core.client.impl.ClientSessionInternal;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionQueueQueryResponseMessage;
 import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
@@ -142,7 +143,8 @@ public abstract class SessionContext {
    public abstract void sendFullMessage(ICoreMessage msgI,
                                         boolean sendBlocking,
                                         SendAcknowledgementHandler handler,
-                                        SimpleString defaultAddress) throws ActiveMQException;
+                                        SimpleString defaultAddress,
+                                        int senderID) throws ActiveMQException;
 
    /**
     * it should return the number of credits (or bytes) used to send this packet
@@ -159,6 +161,7 @@ public abstract class SessionContext {
                                              boolean lastChunk,
                                              byte[] chunk,
                                              int reconnectID,
+                                             int senderID,
                                              SendAcknowledgementHandler messageHandler) throws ActiveMQException;
 
    public abstract int sendServerLargeMessageChunk(Message msgI,
@@ -166,6 +169,7 @@ public abstract class SessionContext {
                                                    boolean sendBlocking,
                                                    boolean lastChunk,
                                                    byte[] chunk,
+                                                   int senderID,
                                                    SendAcknowledgementHandler messageHandler) throws ActiveMQException;
 
    public abstract void setSendAcknowledgementHandler(SendAcknowledgementHandler handler);
@@ -385,4 +389,8 @@ public abstract class SessionContext {
    public abstract void linkFlowControl(SimpleString address, ClientProducerCredits clientProducerCredits);
 
    public abstract boolean isWritable(ReadyListener callback);
+
+   public abstract void createProducer(ClientProducerInternal producer);
+
+   public abstract void removeProducer(int id);
 }
diff --git a/artemis-core-client/src/main/resources/activemq-version.properties b/artemis-core-client/src/main/resources/activemq-version.properties
index 8ca160b89e..7295b14231 100644
--- a/artemis-core-client/src/main/resources/activemq-version.properties
+++ b/artemis-core-client/src/main/resources/activemq-version.properties
@@ -20,4 +20,4 @@ activemq.version.minorVersion=${activemq.version.minorVersion}
 activemq.version.microVersion=${activemq.version.microVersion}
 activemq.version.incrementingVersion=${activemq.version.incrementingVersion}
 activemq.version.versionTag=${activemq.version.versionTag}
-activemq.version.compatibleVersionList=121,122,123,124,125,126,127,128,129,130,131,132,133
+activemq.version.compatibleVersionList=121,122,123,124,125,126,127,128,129,130,131,132,133,134
diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/consumers.js b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/consumers.js
index 8312e44b53..3da804108e 100644
--- a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/consumers.js
+++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/consumers.js
@@ -98,7 +98,15 @@ var Artemis;
               {name: "Address", visible: true},
               {name: "Remote Address", visible: true},
               {name: "Local Address", visible: true},
-              {name: "Creation Time", visible: true}
+              {name: "Creation Time", visible: true},
+              {name: "Messages in Transit", visible: false},
+              {name: "Messages in Transit Size", visible: false},
+              {name: "Messages Delivered", visible: false},
+              {name: "Messages Delivered Size", visible: false},
+              {name: "Messages Acknowledged", visible: false},
+              {name: "Messages Acknowledged awaiting Commit", visible: false},
+              {name: "Last Delivered Time", visible: false},
+              {name: "Last Acknowledged Time", visible: false}
          ]
         };
 
@@ -130,7 +138,13 @@ var Artemis;
                 {id: 'queue', name: 'Queue'},
                 {id: 'protocol', name: 'Protocol'},
                 {id: 'localAddress', name: 'Local Address'},
-                {id: 'remoteAddress', name: 'Remote Address'}
+                {id: 'remoteAddress', name: 'Remote Address'},
+                {id: 'messagesInTransit', name: 'Messages in Transit'},
+                {id: 'messagesInTransitSize', name: 'Messages in Transit Size'},
+                {id: 'messagesDelivered', name: 'Messages Delivered'},
+                {id: 'messagesDeliveredSize', name: 'Messages Delivered Size'},
+                {id: 'messagesAcknowledged', name: 'Messages Acknowledged'},
+                {id: 'messagesAcknowledgedAwaitingCommit', name: 'Messages Acknowledged awaiting Commit'}
             ],
             operationOptions: [
                 {id: 'EQUALS', name: 'Equals'},
@@ -181,7 +195,15 @@ var Artemis;
             { header: 'Address', itemField: 'addressName' , htmlTemplate: 'consumers-anchor-column-template', colActionFn: (item) => selectAddress(item.idx) },
             { header: 'Remote Address', itemField: 'remoteAddress' },
             { header: 'Local Address', itemField: 'localAddress' },
-            { header: 'Creation Time', itemField: 'creationTime' }
+            { header: 'Creation Time', itemField: 'creationTime' },
+            { header: 'Messages in Transit', itemField: 'messagesInTransit' },
+            { header: 'Messages in Transit Size', itemField: 'messagesInTransitSize' },
+            { header: 'Messages Delivered', itemField: 'messagesDelivered' },
+            { header: 'Messages Delivered Size', itemField: 'messagesDeliveredSize' },
+            { header: 'Messages Acknowledged', itemField: 'messagesAcknowledged' },
+            { header: 'Messages Acknowledged awaiting Commit', itemField: 'messagesAcknowledgedAwaitingCommit' },
+            { header: 'Last Delivered Time', itemField: 'lastDeliveredTime', templateFn: function(value) { return formatTimestamp(value);} },
+            { header: 'Last Acknowledged Time', itemField: 'lastAcknowledgedTime' ,  templateFn: function(value) { return formatTimestamp(value);} }
         ];
 
         ctrl.refresh = function () {
@@ -279,6 +301,25 @@ var Artemis;
             }
         };
 
+        function formatTimestamp(timestamp) {
+             Artemis.log.info("in timestamp " + timestamp + " " + (typeof timestamp !== "number"));
+             if (isNaN(timestamp) || typeof timestamp !== "number") {
+                Artemis.log.info("returning timestamp " + timestamp + " " + (typeof timestamp !== "number"));
+                return timestamp;
+             }
+             if (timestamp === 0) {
+                return "N/A";
+             }
+             var d = new Date(timestamp);
+             // "yyyy-MM-dd HH:mm:ss"
+             //add 1 to month as getmonth returns the position not the actual month
+             return d.getFullYear() + "-" + pad2(d.getMonth() + 1) + "-" + pad2(d.getDate()) + " " + pad2(d.getHours()) + ":" + pad2(d.getMinutes()) + ":" + pad2(d.getSeconds());
+        }
+        function pad2(value) {
+            return (value < 10 ? '0' : '') + value;
+        }
+
+
         ctrl.pagination.setOperation(ctrl.loadOperation);
 
         function onError(response) {
diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/producers.js b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/producers.js
index 9602336886..a58ebcef84 100644
--- a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/producers.js
+++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/producers.js
@@ -72,6 +72,7 @@ var Artemis;
            ordering: false,
            columns: [
                 {name: "ID", visible: true},
+                {name: "Name", visible: true},
                 {name: "Session", visible: true},
                 {name: "Client ID", visible: true},
                 {name: "Protocol", visible: true},
@@ -79,7 +80,10 @@ var Artemis;
                 {name: "Validated User", visible: false},
                 {name: "Address", visible: true},
                 {name: "Remote Address", visible: true},
-                {name: "Local Address", visible: true}
+                {name: "Local Address", visible: true},
+                {name: "Messages Sent", visible: false},
+                {name: "Messages Sent Size", visible: false},
+                {name: "Last Produced Message ID", visible: false}
            ]
           };
 
@@ -103,6 +107,7 @@ var Artemis;
         ctrl.filter = {
             fieldOptions: [
                 {id: 'id', name: 'ID'},
+                {id: 'name', name: 'Name'},
                 {id: 'session', name: 'Session'},
                 {id: 'clientID', name: 'Client ID'},
                 {id: 'user', name: 'User'},
@@ -140,6 +145,7 @@ var Artemis;
         };
         ctrl.tableColumns = [
             { header: 'ID', itemField: 'id' },
+            { header: 'Name', itemField: 'name' },
             { header: 'Session', itemField: 'session' , htmlTemplate: 'producers-anchor-column-template', colActionFn: (item) => selectSession(item.idx) },
             { header: 'Client ID', itemField: 'clientID' },
             { header: 'Protocol', itemField: 'protocol' },
@@ -147,7 +153,10 @@ var Artemis;
             { header: 'Validated User', name: 'validatedUser'},
             { header: 'Address', itemField: 'addressName' , htmlTemplate: 'producers-anchor-column-template', colActionFn: (item) => selectAddress(item.idx) },
             { header: 'Remote Address', itemField: 'remoteAddress' },
-            { header: 'Local Address', itemField: 'localAddress' }
+            { header: 'Local Address', itemField: 'localAddress' },
+            { header: 'Messages Sent', itemField: 'msgSent'},
+            { header: 'Messages Sent Size', itemField: 'msgSizeSent'},
+            { header: 'Last Produced Message ID', itemField: 'lastProducedMessageID'}
         ];
 
         ctrl.refresh = function () {
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPSessionCallback.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPSessionCallback.java
index 637cdf10f2..0603688a96 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPSessionCallback.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPSessionCallback.java
@@ -41,7 +41,6 @@ import org.apache.activemq.artemis.core.server.MessageReference;
 import org.apache.activemq.artemis.core.server.QueueQueryResult;
 import org.apache.activemq.artemis.core.server.RoutingContext;
 import org.apache.activemq.artemis.core.server.ServerConsumer;
-import org.apache.activemq.artemis.core.server.ServerProducer;
 import org.apache.activemq.artemis.core.server.ServerSession;
 import org.apache.activemq.artemis.core.server.impl.AddressInfo;
 import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
@@ -202,14 +201,14 @@ public class AMQPSessionCallback implements SessionCallback {
                                                            false, // boolean autoCommitAcks,
                                                            false, // boolean preAcknowledge,
                                                            true, //boolean xa,
-                                                           null, this, true, operationContext, manager.getPrefixes(), manager.getSecurityDomain());
+                                                           null, this, true, operationContext, manager.getPrefixes(), manager.getSecurityDomain(), false);
       } else {
          serverSession = manager.getServer().createSession(name, connection.getUser(), connection.getPassword(), ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, protonSPI.getProtonConnectionDelegate(), // RemotingConnection remotingConnection,
                                                            false, // boolean autoCommitSends
                                                            false, // boolean autoCommitAcks,
                                                            false, // boolean preAcknowledge,
                                                            true, //boolean xa,
-                                                           null, this, true, operationContext, manager.getPrefixes(), manager.getSecurityDomain(), connection.getValidatedUser());
+                                                           null, this, true, operationContext, manager.getPrefixes(), manager.getSecurityDomain(), connection.getValidatedUser(), false);
       }
    }
 
@@ -532,7 +531,7 @@ public class AMQPSessionCallback implements SessionCallback {
       OperationContext oldContext = recoverContext();
       try {
          if (invokeIncoming((AMQPMessage) message, (ActiveMQProtonRemotingConnection) transportConnection.getProtocolConnection()) == null) {
-            serverSession.send(transaction, message, directDeliver, false, routingContext);
+            serverSession.send(transaction, message, directDeliver, receiver.getName(), false, routingContext);
 
             afterIO(new IOCallback() {
                @Override
@@ -744,8 +743,8 @@ public class AMQPSessionCallback implements SessionCallback {
       return protonSPI.invokeOutgoingInterceptors(message, connection);
    }
 
-   public void addProducer(ServerProducer serverProducer) {
-      serverSession.addProducer(serverProducer);
+   public void addProducer(String name, String address) {
+      serverSession.addProducer(name, ProtonProtocolManagerFactory.AMQP_PROTOCOL_NAME, address);
    }
 
    public void removeProducer(String name) {
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPSessionContext.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPSessionContext.java
index 90c271cfde..b64f41f3f8 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPSessionContext.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPSessionContext.java
@@ -24,8 +24,6 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.activemq.artemis.api.core.ActiveMQSecurityException;
 import org.apache.activemq.artemis.core.server.ActiveMQServer;
-import org.apache.activemq.artemis.core.server.ServerProducer;
-import org.apache.activemq.artemis.core.server.impl.ServerProducerImpl;
 import org.apache.activemq.artemis.protocol.amqp.connect.mirror.AMQPMirrorControllerSource;
 import org.apache.activemq.artemis.protocol.amqp.connect.mirror.AMQPMirrorControllerTarget;
 import org.apache.activemq.artemis.protocol.amqp.broker.AMQPSessionCallback;
@@ -160,7 +158,6 @@ public class AMQPSessionContext extends ProtonInitializable {
    }
 
    public void removeReceiver(Receiver receiver) {
-      sessionSPI.removeProducer(receiver.getName());
       receivers.remove(receiver);
    }
 
@@ -229,8 +226,7 @@ public class AMQPSessionContext extends ProtonInitializable {
          AMQPMirrorControllerTarget protonReceiver = new AMQPMirrorControllerTarget(sessionSPI, connection, this, receiver, server);
          protonReceiver.initialize();
          receivers.put(receiver, protonReceiver);
-         ServerProducer serverProducer = new ServerProducerImpl(receiver.getName(), "AMQP", receiver.getTarget().getAddress());
-         sessionSPI.addProducer(serverProducer);
+         sessionSPI.addProducer(receiver.getName(), receiver.getTarget().getAddress());
          receiver.setContext(protonReceiver);
          HashMap<Symbol, Object> brokerIDProperties = new HashMap<>();
          brokerIDProperties.put(AMQPMirrorControllerSource.BROKER_ID, server.getNodeID().toString());
@@ -255,8 +251,7 @@ public class AMQPSessionContext extends ProtonInitializable {
          ProtonServerReceiverContext protonReceiver = new ProtonServerReceiverContext(sessionSPI, connection, this, receiver);
          protonReceiver.initialize();
          receivers.put(receiver, protonReceiver);
-         ServerProducer serverProducer = new ServerProducerImpl(receiver.getName(), "AMQP", receiver.getTarget().getAddress());
-         sessionSPI.addProducer(serverProducer);
+         sessionSPI.addProducer(receiver.getName(), receiver.getTarget().getAddress());
          receiver.setContext(protonReceiver);
          connection.runNow(() -> {
             receiver.open();
diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonServerReceiverContext.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonServerReceiverContext.java
index 199e8c2d95..33e87bd5ed 100644
--- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonServerReceiverContext.java
+++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/ProtonServerReceiverContext.java
@@ -270,6 +270,7 @@ public class ProtonServerReceiverContext extends ProtonAbstractReceiver {
    @Override
    public void close(boolean remoteLinkClose) throws ActiveMQAMQPException {
       super.close(remoteLinkClose);
+      sessionSPI.removeProducer(receiver.getName());
       org.apache.qpid.proton.amqp.messaging.Target target = (org.apache.qpid.proton.amqp.messaging.Target) receiver.getRemoteTarget();
       if (target != null && target.getDynamic() && (target.getExpiryPolicy() == TerminusExpiryPolicy.LINK_DETACH || target.getExpiryPolicy() == TerminusExpiryPolicy.SESSION_END)) {
          try {
diff --git a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnectionManager.java b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnectionManager.java
index fc6b5fd91b..fe1b9c50c6 100644
--- a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnectionManager.java
+++ b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnectionManager.java
@@ -169,7 +169,9 @@ public class MQTTConnectionManager {
                                                          MQTTUtil.SESSION_AUTO_CREATE_QUEUE,
                                                          server.newOperationContext(),
                                                          session.getProtocolManager().getPrefixes(),
-                                                         session.getProtocolManager().getSecurityDomain(), validatedUser);
+                                                         session.getProtocolManager().getSecurityDomain(),
+                                                         validatedUser,
+                                                         false);
       return (ServerSessionImpl) serverSession;
    }
 
diff --git a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTPublishManager.java b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTPublishManager.java
index c65cf2186b..0059140a31 100644
--- a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTPublishManager.java
+++ b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTPublishManager.java
@@ -42,8 +42,10 @@ import org.apache.activemq.artemis.core.io.IOCallback;
 import org.apache.activemq.artemis.core.protocol.mqtt.exceptions.DisconnectException;
 import org.apache.activemq.artemis.core.server.Queue;
 import org.apache.activemq.artemis.core.server.ServerConsumer;
+import org.apache.activemq.artemis.core.server.ServerProducer;
 import org.apache.activemq.artemis.core.server.impl.ServerSessionImpl;
 import org.apache.activemq.artemis.core.transaction.Transaction;
+import org.apache.activemq.artemis.utils.UUIDGenerator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import java.lang.invoke.MethodHandles;
@@ -72,6 +74,10 @@ public class MQTTPublishManager {
 
    private SimpleString managementAddress;
 
+   private final String senderName = UUIDGenerator.getInstance().generateUUID().toString();
+
+   private boolean createProducer = true;
+
    private ServerConsumer managementConsumer;
 
    private MQTTSession session;
@@ -173,6 +179,10 @@ public class MQTTPublishManager {
     */
    void sendToQueue(MqttPublishMessage message, boolean internal) throws Exception {
       synchronized (lock) {
+         if (createProducer) {
+            session.getServerSession().addProducer(senderName, MQTTProtocolManagerFactory.MQTT_PROTOCOL_NAME, ServerProducer.ANONYMOUS);
+            createProducer = false;
+         }
          String topic = message.variableHeader().topicName();
          if (session.getVersion() == MQTTVersion.MQTT_5) {
             Integer alias = MQTTUtil.getProperty(Integer.class, message.variableHeader().properties(), TOPIC_ALIAS);
@@ -206,7 +216,6 @@ public class MQTTPublishManager {
          if (qos > 0) {
             serverMessage.setDurable(MQTTUtil.DURABLE_MESSAGES);
          }
-
          int messageId = message.variableHeader().packetId();
          if (qos < 2 || !state.getPubRec().contains(messageId)) {
             if (qos == 2 && !internal)
@@ -217,7 +226,7 @@ public class MQTTPublishManager {
                if (session.getServer().getAddressInfo(address) == null && session.getServer().getAddressSettingsRepository().getMatch(coreAddress).isAutoCreateAddresses()) {
                   session.getServerSession().createAddress(address, RoutingType.MULTICAST, true);
                }
-               session.getServerSession().send(tx, serverMessage, true, false);
+               session.getServerSession().send(tx, serverMessage, true, senderName, false);
 
                if (message.fixedHeader().isRetain()) {
                   ByteBuf payload = message.payload();
@@ -303,7 +312,7 @@ public class MQTTPublishManager {
          if (ref != null) {
             Message m = MQTTUtil.createPubRelMessage(session, getManagementAddress(), messageId);
             //send the management message via the internal server session to bypass security.
-            session.getInternalServerSession().send(m, true);
+            session.getInternalServerSession().send(m, true, senderName);
             session.getServerSession().individualAcknowledge(ref.getB(), ref.getA());
             releaseFlowControl(ref.getB());
          } else {
diff --git a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java
index 943d9a3cf2..bb22cc48d0 100644
--- a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java
+++ b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java
@@ -837,7 +837,7 @@ public class OpenWireConnection extends AbstractRemotingConnection implements Se
    }
 
    private void createInternalSession(ConnectionInfo info) throws Exception {
-      internalSession = server.createSession(UUIDGenerator.getInstance().generateStringUUID(), context.getUserName(), info.getPassword(), -1, this, true, false, false, false, null, null, true, operationContext, protocolManager.getPrefixes(), protocolManager.getSecurityDomain(), validatedUser);
+      internalSession = server.createSession(UUIDGenerator.getInstance().generateStringUUID(), context.getUserName(), info.getPassword(), -1, this, true, false, false, false, null, null, true, operationContext, protocolManager.getPrefixes(), protocolManager.getSecurityDomain(), validatedUser, false);
    }
 
    //raise the refCount of context
@@ -1261,6 +1261,10 @@ public class OpenWireConnection extends AbstractRemotingConnection implements Se
             }
 
             ss.addProducer(info);
+            getSession(info.getProducerId().getParentId()).getCoreSession().addProducer(
+                  info.getProducerId().toString(),
+                  OpenWireProtocolManagerFactory.OPENWIRE_PROTOCOL_NAME,
+                  info.getDestination() != null ? info.getDestination().getPhysicalName() : null);
 
          }
          return null;
@@ -1290,6 +1294,7 @@ public class OpenWireConnection extends AbstractRemotingConnection implements Se
          }
          synchronized (producerExchanges) {
             producerExchanges.remove(id);
+            getSession(id.getParentId()).getCoreSession().removeProducer(id.toString());
          }
          return null;
       }
diff --git a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/amq/AMQConsumer.java b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/amq/AMQConsumer.java
index 057160ba33..d064d5036c 100644
--- a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/amq/AMQConsumer.java
+++ b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/amq/AMQConsumer.java
@@ -362,6 +362,7 @@ public class AMQConsumer {
             if (ack.isIndividualAck() || ack.isStandardAck()) {
                for (MessageReference ref : ackList) {
                   ref.acknowledge(transaction, serverConsumer);
+                  serverConsumer.metricsAcknowledge(ref, transaction);
                   removeRolledback(ref);
                }
             } else if (ack.isPoisonAck()) {
diff --git a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/amq/AMQSession.java b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/amq/AMQSession.java
index 28caa08f92..aa7b899b9c 100644
--- a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/amq/AMQSession.java
+++ b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/amq/AMQSession.java
@@ -132,7 +132,7 @@ public class AMQSession implements SessionCallback {
       // now
 
       try {
-         coreSession = server.createSession(name, username, password, minLargeMessageSize, connection, true, false, false, false, null, this, true, connection.getOperationContext(), protocolManager.getPrefixes(), protocolManager.getSecurityDomain(), connection.getValidatedUser());
+         coreSession = server.createSession(name, username, password, minLargeMessageSize, connection, true, false, false, false, null, this, true, connection.getOperationContext(), protocolManager.getPrefixes(), protocolManager.getSecurityDomain(), connection.getValidatedUser(), false);
       } catch (Exception e) {
          logger.error("error init session", e);
       }
@@ -392,7 +392,6 @@ public class AMQSession implements SessionCallback {
 
       assert clientId.toString().equals(this.connection.getState().getInfo().getClientId()) : "Session cached clientId must be the same of the connection";
       originalCoreMsg.putStringProperty(MessageUtil.CONNECTION_ID_PROPERTY_NAME, clientId);
-
       /* ActiveMQ failover transport will attempt to reconnect after connection failure.  Any sent messages that did
       * not receive acks will be resent.  (ActiveMQ broker handles this by returning a last sequence id received to
       * the client).  To handle this in Artemis we use a duplicate ID cache.  To do this we check to see if the
@@ -438,7 +437,7 @@ public class AMQSession implements SessionCallback {
                restoreAutoRead();
             }
 
-            getCoreSession().send(coreMsg, false, dest.isTemporary());
+            getCoreSession().send(coreMsg, false, producerInfo.getProducerId().toString(), dest.isTemporary());
 
             if (count == null || count.decrementAndGet() == 0) {
                if (sendProducerAck) {
@@ -462,7 +461,7 @@ public class AMQSession implements SessionCallback {
          Exception exceptionToSend = null;
 
          try {
-            getCoreSession().send(coreMsg, false, dest.isTemporary());
+            getCoreSession().send(coreMsg, false, producerInfo.getProducerId().toString(), dest.isTemporary());
          } catch (Exception e) {
             logger.debug("Sending exception to the client", e);
             exceptionToSend = e;
diff --git a/artemis-protocols/artemis-openwire-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/openwire/amq/OpenWireConnectionTest.java b/artemis-protocols/artemis-openwire-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/openwire/amq/OpenWireConnectionTest.java
index f9c969c192..9071c755a5 100644
--- a/artemis-protocols/artemis-openwire-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/openwire/amq/OpenWireConnectionTest.java
+++ b/artemis-protocols/artemis-openwire-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/openwire/amq/OpenWireConnectionTest.java
@@ -71,7 +71,7 @@ public class OpenWireConnectionTest {
       ServerSession serverSession = Mockito.mock(ServerSession.class);
       Mockito.when(serverSession.getName()).thenReturn("session");
       Mockito.doReturn(serverSession).when(server).createSession(Mockito.anyString(), Mockito.any(), Mockito.any(), Mockito.anyInt(), Mockito.any(), Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.anyBoolean(),
-                                                                 Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.anyString(), Mockito.any());
+                                                                 Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any(), Mockito.any(), Mockito.anyString(), Mockito.any(), Mockito.anyBoolean());
 
       OpenWireProtocolManager openWireProtocolManager = new OpenWireProtocolManager(null, server,null, null);
       openWireProtocolManager.setSecurityDomain("securityDomain");
diff --git a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompProtocolManager.java b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompProtocolManager.java
index ab7e004f80..291b595399 100644
--- a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompProtocolManager.java
+++ b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompProtocolManager.java
@@ -247,7 +247,7 @@ public class StompProtocolManager extends AbstractProtocolManager<StompFrame, St
          stompSession = new StompSession(connection, this, server.getStorageManager().newContext(server.getExecutorFactory().getExecutor()));
          String name = UUIDGenerator.getInstance().generateStringUUID();
          final String validatedUser = server.validateUser(connection.getLogin(), connection.getPasscode(), connection, getSecurityDomain());
-         ServerSession session = server.createSession(name, connection.getLogin(), connection.getPasscode(), ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, connection, !transacted, false, false, false, null, stompSession, true, server.newOperationContext(), getPrefixes(), getSecurityDomain(), validatedUser);
+         ServerSession session = server.createSession(name, connection.getLogin(), connection.getPasscode(), ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, connection, !transacted, false, false, false, null, stompSession, true, server.newOperationContext(), getPrefixes(), getSecurityDomain(), validatedUser, false);
          stompSession.setServerSession(session);
          sessions.put(id, stompSession);
       }
diff --git a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompSession.java b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompSession.java
index 2d9bddfee2..a22072f83e 100644
--- a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompSession.java
+++ b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompSession.java
@@ -41,6 +41,7 @@ import org.apache.activemq.artemis.core.server.LargeServerMessage;
 import org.apache.activemq.artemis.core.server.MessageReference;
 import org.apache.activemq.artemis.core.server.Queue;
 import org.apache.activemq.artemis.core.server.ServerConsumer;
+import org.apache.activemq.artemis.core.server.ServerProducer;
 import org.apache.activemq.artemis.core.server.ServerSession;
 import org.apache.activemq.artemis.core.server.impl.ServerSessionImpl;
 import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
@@ -55,11 +56,16 @@ import org.slf4j.LoggerFactory;
 import java.lang.invoke.MethodHandles;
 
 import static org.apache.activemq.artemis.core.protocol.stomp.ActiveMQStompProtocolMessageBundle.BUNDLE;
+import static org.apache.activemq.artemis.core.protocol.stomp.StompProtocolManagerFactory.STOMP_PROTOCOL_NAME;
 
 public class StompSession implements SessionCallback {
 
    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
+   private final String senderName = UUIDGenerator.getInstance().generateUUID().toString();
+
+   private boolean createProducer = true;
+
    private final StompProtocolManager manager;
 
    private final StompConnection connection;
@@ -217,6 +223,7 @@ public class StompSession implements SessionCallback {
 
    @Override
    public void closed() {
+      session.removeProducer(senderName);
    }
 
    @Override
@@ -379,10 +386,18 @@ public class StompSession implements SessionCallback {
    }
 
    public void sendInternal(Message message, boolean direct) throws Exception {
-      session.send(message, direct);
+      if (createProducer) {
+         session.addProducer(senderName, STOMP_PROTOCOL_NAME, ServerProducer.ANONYMOUS);
+         createProducer = false;
+      }
+      session.send(message, direct, senderName);
    }
 
    public void sendInternalLarge(CoreMessage message, boolean direct) throws Exception {
+      if (createProducer) {
+         session.addProducer(senderName, STOMP_PROTOCOL_NAME, ServerProducer.ANONYMOUS);
+         createProducer = false;
+      }
       int headerSize = message.getHeadersAndPropertiesEncodeSize();
       if (headerSize >= connection.getMinLargeMessageSize()) {
          throw BUNDLE.headerTooBig();
@@ -402,7 +417,7 @@ public class StompSession implements SessionCallback {
 
       largeMessage.toMessage().putLongProperty(Message.HDR_LARGE_BODY_SIZE, bytes.length);
 
-      session.send(largeMessage.toMessage(), direct);
+      session.send(largeMessage.toMessage(), direct, senderName);
    }
 
 }
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/AbstractControl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/AbstractControl.java
index 98e966ef6a..205956394e 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/AbstractControl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/AbstractControl.java
@@ -122,7 +122,7 @@ public abstract class AbstractControl extends StandardMBean {
                                                          Integer.MAX_VALUE, fakeConnection,
                                                          true, true, false,
                                                          false, address.toString(), fakeConnection.callback,
-                                                         false, new DummyOperationContext(), Collections.emptyMap(), null, validatedUser);
+                                                         false, new DummyOperationContext(), Collections.emptyMap(), null, validatedUser, false);
       try {
          CoreMessage message = new CoreMessage(storageManager.generateID(), 50);
          if (headers != null) {
@@ -159,7 +159,7 @@ public abstract class AbstractControl extends StandardMBean {
          }
 
          // There's no point on direct delivery using the management thread, use false here
-         serverSession.send(message, false);
+         serverSession.send(message, false, null);
          return "" + message.getMessageID();
       } finally {
          try {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java
index 25deb59e09..bca62eedfa 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java
@@ -79,6 +79,7 @@ import org.apache.activemq.artemis.core.config.TransformerConfiguration;
 import org.apache.activemq.artemis.core.filter.Filter;
 import org.apache.activemq.artemis.core.management.impl.view.AddressView;
 import org.apache.activemq.artemis.core.management.impl.view.ConnectionView;
+import org.apache.activemq.artemis.core.management.impl.view.ConsumerField;
 import org.apache.activemq.artemis.core.management.impl.view.ConsumerView;
 import org.apache.activemq.artemis.core.management.impl.view.ProducerView;
 import org.apache.activemq.artemis.core.management.impl.view.QueueView;
@@ -107,6 +108,7 @@ import org.apache.activemq.artemis.core.server.ConnectorServiceFactory;
 import org.apache.activemq.artemis.core.server.Consumer;
 import org.apache.activemq.artemis.core.server.Divert;
 import org.apache.activemq.artemis.core.server.JournalType;
+import org.apache.activemq.artemis.core.server.MessageReference;
 import org.apache.activemq.artemis.core.server.Queue;
 import org.apache.activemq.artemis.core.server.ServerConsumer;
 import org.apache.activemq.artemis.core.server.ServerProducer;
@@ -2609,7 +2611,7 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active
       try {
          Set<ServerProducer> producers = new HashSet<>();
          for (ServerSession session : server.getSessions()) {
-            producers.addAll(session.getServerProducers().values());
+            producers.addAll(session.getServerProducers());
          }
          ProducerView view = new ProducerView(server);
          view.setCollection(producers);
@@ -2767,7 +2769,24 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active
    }
 
    private JsonObject toJSONObject(ServerConsumer consumer) throws Exception {
-      JsonObjectBuilder obj = JsonLoader.createObjectBuilder().add("consumerID", consumer.getID()).add("connectionID", consumer.getConnectionID().toString()).add("sessionID", consumer.getSessionID()).add("queueName", consumer.getQueue().getName().toString()).add("browseOnly", consumer.isBrowseOnly()).add("creationTime", consumer.getCreationTime()).add("deliveringCount", consumer.getDeliveringMessages().size());
+      List<MessageReference> deliveringMessages = consumer.getDeliveringMessages();
+      JsonObjectBuilder obj = JsonLoader.createObjectBuilder()
+            .add(ConsumerField.ID.getAlternativeName(), consumer.getID())
+            .add(ConsumerField.CONNECTION.getAlternativeName(), consumer.getConnectionID().toString())
+            .add(ConsumerField.SESSION.getAlternativeName(), consumer.getSessionID())
+            .add(ConsumerField.QUEUE.getAlternativeName(), consumer.getQueue().getName().toString())
+            .add(ConsumerField.BROWSE_ONLY.getName(), consumer.isBrowseOnly())
+            .add(ConsumerField.CREATION_TIME.getName(), consumer.getCreationTime())
+            // deliveringCount is renamed as MESSAGES_IN_TRANSIT but left in json for backward compatibility
+            .add(ConsumerField.MESSAGES_IN_TRANSIT.getAlternativeName(), consumer.getMessagesInTransit())
+            .add(ConsumerField.MESSAGES_IN_TRANSIT.getName(), consumer.getMessagesInTransit())
+            .add(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName(), consumer.getMessagesInTransitSize())
+            .add(ConsumerField.MESSAGES_DELIVERED.getName(), consumer.getMessagesDelivered())
+            .add(ConsumerField.MESSAGES_DELIVERED_SIZE.getName(), consumer.getMessagesDeliveredSize())
+            .add(ConsumerField.MESSAGES_ACKNOWLEDGED.getName(), consumer.getMessagesAcknowledged())
+            .add(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName(), consumer.getMessagesAcknowledgedAwaitingCommit())
+            .add(ConsumerField.LAST_DELIVERED_TIME.getName(), consumer.getLastDeliveredTime())
+            .add(ConsumerField.LAST_ACKNOWLEDGED_TIME.getName(), consumer.getLastAcknowledgedTime());
       if (consumer.getFilter() != null) {
          obj.add("filter", consumer.getFilter().getFilterString().toString());
       }
@@ -4407,14 +4426,6 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active
       }
    }
 
-   public String[] listTargetAddresses(final String sessionID) {
-      ServerSession session = server.getSessionByID(sessionID);
-      if (session != null) {
-         return session.getTargetAddresses();
-      }
-      return new String[0];
-   }
-
    @Override
    public void onNotification(org.apache.activemq.artemis.core.server.management.Notification notification) {
       if (!(notification.getType() instanceof CoreNotificationType))
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/QueueControlImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/QueueControlImpl.java
index 9bced82671..5b37b6570d 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/QueueControlImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/QueueControlImpl.java
@@ -36,6 +36,7 @@ import org.apache.activemq.artemis.api.core.management.QueueControl;
 import org.apache.activemq.artemis.api.core.management.ResourceNames;
 import org.apache.activemq.artemis.core.filter.Filter;
 import org.apache.activemq.artemis.core.filter.impl.FilterImpl;
+import org.apache.activemq.artemis.core.management.impl.view.ConsumerField;
 import org.apache.activemq.artemis.core.messagecounter.MessageCounter;
 import org.apache.activemq.artemis.core.messagecounter.impl.MessageCounterHelper;
 import org.apache.activemq.artemis.core.persistence.StorageManager;
@@ -1826,9 +1827,20 @@ public class QueueControlImpl extends AbstractControl implements QueueControl {
 
             if (consumer instanceof ServerConsumer) {
                ServerConsumer serverConsumer = (ServerConsumer) consumer;
-
-               JsonObjectBuilder obj = JsonLoader.createObjectBuilder().add("consumerID", serverConsumer.getID()).add("connectionID", serverConsumer.getConnectionID().toString()).add("sessionID", serverConsumer.getSessionID()).add("browseOnly", serverConsumer.isBrowseOnly()).add("creationTime", serverConsumer.getCreationTime());
-
+               JsonObjectBuilder obj = JsonLoader.createObjectBuilder()
+                       .add(ConsumerField.ID.getAlternativeName(), serverConsumer.getID())
+                       .add(ConsumerField.CONNECTION.getAlternativeName(), serverConsumer.getConnectionID().toString())
+                       .add(ConsumerField.SESSION.getAlternativeName(), serverConsumer.getSessionID())
+                       .add(ConsumerField.BROWSE_ONLY.getName(), serverConsumer.isBrowseOnly())
+                       .add(ConsumerField.CREATION_TIME.getName(), serverConsumer.getCreationTime())
+                       .add(ConsumerField.MESSAGES_IN_TRANSIT.getName(), serverConsumer.getMessagesInTransit())
+                       .add(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName(), serverConsumer.getMessagesInTransitSize())
+                       .add(ConsumerField.MESSAGES_DELIVERED.getName(), serverConsumer.getMessagesDelivered())
+                       .add(ConsumerField.MESSAGES_DELIVERED_SIZE.getName(), serverConsumer.getMessagesDeliveredSize())
+                       .add(ConsumerField.MESSAGES_ACKNOWLEDGED.getName(), serverConsumer.getMessagesAcknowledged())
+                       .add(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName(), serverConsumer.getMessagesAcknowledgedAwaitingCommit())
+                       .add(ConsumerField.LAST_DELIVERED_TIME.getName(), serverConsumer.getLastDeliveredTime())
+                       .add(ConsumerField.LAST_ACKNOWLEDGED_TIME.getName(), serverConsumer.getLastAcknowledgedTime());
                jsonArray.add(obj);
             }
 
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConsumerField.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConsumerField.java
index c0d2cf38f4..c4066a19a5 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConsumerField.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConsumerField.java
@@ -20,9 +20,10 @@ import java.util.Map;
 import java.util.TreeMap;
 
 public enum ConsumerField {
-   ID("id"),
-   SESSION("session"),
-   QUEUE("queue"),
+   ID("id", "consumerID"),
+   SESSION("session", "sessionID"),
+   CONNECTION("connection", "connectionID"),
+   QUEUE("queue", "queueName"),
    FILTER("filter"),
    ADDRESS("address"),
    USER("user"),
@@ -32,7 +33,16 @@ public enum ConsumerField {
    LOCAL_ADDRESS("localAddress"),
    REMOTE_ADDRESS("remoteAddress"),
    QUEUE_TYPE("queueType"),
-   CREATION_TIME("creationTime");
+   BROWSE_ONLY("browseOnly"),
+   CREATION_TIME("creationTime"),
+   MESSAGES_IN_TRANSIT("messagesInTransit", "deliveringCount"),
+   MESSAGES_IN_TRANSIT_SIZE("messagesInTransitSize"),
+   MESSAGES_DELIVERED("messagesDelivered"),
+   MESSAGES_DELIVERED_SIZE("messagesDeliveredSize"),
+   MESSAGES_ACKNOWLEDGED("messagesAcknowledged"),
+   MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT("messagesAcknowledgedAwaitingCommit"),
+   LAST_DELIVERED_TIME("lastDeliveredTime"),
+   LAST_ACKNOWLEDGED_TIME("lastAcknowledgedTime");
 
    private static final Map<String, ConsumerField> lookup = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
 
@@ -44,12 +54,28 @@ public enum ConsumerField {
 
    private final String name;
 
+   private final String alternativeName;
+
    public String getName() {
       return name;
    }
 
+   /**
+    * There is some inconsistency with some json objects returned for consumers because they were hard coded.
+    * This is just to track the differences and provide backward compatibility.
+    * @return the old alternative name
+    */
+   public String getAlternativeName() {
+      return alternativeName;
+   }
+
    ConsumerField(String name) {
+      this(name, "");
+   }
+
+   ConsumerField(String name, String alternativeName) {
       this.name = name;
+      this.alternativeName = alternativeName;
    }
 
    public static ConsumerField valueOfName(String name) {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConsumerView.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConsumerView.java
index 77ffb304ae..97eaf93ee2 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConsumerView.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConsumerView.java
@@ -16,6 +16,7 @@
  */
 package org.apache.activemq.artemis.core.management.impl.view;
 
+import org.apache.activemq.artemis.core.management.impl.ActiveMQServerControlImpl;
 import org.apache.activemq.artemis.json.JsonObjectBuilder;
 import java.util.Date;
 
@@ -46,7 +47,7 @@ public class ConsumerView extends ActiveMQAbstractView<ServerConsumer> {
    @Override
    public JsonObjectBuilder toJson(ServerConsumer consumer) {
       ServerSession session = server.getSessionByID(consumer.getSessionID());
-
+      ActiveMQServerControlImpl serverControl = server.getActiveMQServerControl();
       //if session is not available then consumer is not in valid state - ignore
       if (session == null) {
          return null;
@@ -71,7 +72,15 @@ public class ConsumerView extends ActiveMQAbstractView<ServerConsumer> {
          .add(ConsumerField.ADDRESS.getName(), toString(consumer.getQueueAddress()))
          .add(ConsumerField.LOCAL_ADDRESS.getName(), toString(consumer.getConnectionLocalAddress()))
          .add(ConsumerField.REMOTE_ADDRESS.getName(), toString(consumer.getConnectionRemoteAddress()))
-         .add(ConsumerField.CREATION_TIME.getName(), new Date(consumer.getCreationTime()).toString());
+         .add(ConsumerField.CREATION_TIME.getName(), new Date(consumer.getCreationTime()).toString())
+         .add(ConsumerField.MESSAGES_IN_TRANSIT.getName(), toString(consumer.getMessagesInTransit()))
+         .add(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName(), toString(consumer.getMessagesInTransitSize()))
+         .add(ConsumerField.MESSAGES_DELIVERED.getName(), toString(consumer.getMessagesDelivered()))
+         .add(ConsumerField.MESSAGES_DELIVERED_SIZE.getName(), toString(consumer.getMessagesDeliveredSize()))
+         .add(ConsumerField.MESSAGES_ACKNOWLEDGED.getName(), toString(consumer.getMessagesAcknowledged()))
+         .add(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName(), toString(consumer.getMessagesAcknowledgedAwaitingCommit()))
+         .add(ConsumerField.LAST_DELIVERED_TIME.getName(), consumer.getLastDeliveredTime())
+         .add(ConsumerField.LAST_ACKNOWLEDGED_TIME.getName(), consumer.getLastAcknowledgedTime());
       return obj;
    }
 
@@ -111,6 +120,22 @@ public class ConsumerView extends ActiveMQAbstractView<ServerConsumer> {
             return consumer.getConnectionRemoteAddress();
          case CREATION_TIME:
             return new Date(consumer.getCreationTime());
+         case MESSAGES_IN_TRANSIT:
+            return consumer.getMessagesInTransit();
+         case MESSAGES_IN_TRANSIT_SIZE:
+            return consumer.getMessagesInTransitSize();
+         case MESSAGES_DELIVERED:
+            return consumer.getMessagesDelivered();
+         case MESSAGES_DELIVERED_SIZE:
+            return consumer.getMessagesDeliveredSize();
+         case MESSAGES_ACKNOWLEDGED:
+            return consumer.getMessagesAcknowledged();
+         case MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT:
+            return consumer.getMessagesAcknowledgedAwaitingCommit();
+         case LAST_DELIVERED_TIME:
+            return consumer.getLastDeliveredTime();
+         case LAST_ACKNOWLEDGED_TIME:
+            return consumer.getLastAcknowledgedTime();
          default:
             throw new IllegalArgumentException("Unsupported field, " + fieldName);
       }
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ProducerField.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ProducerField.java
index 87f9cb2ecc..075f2ccf30 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ProducerField.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ProducerField.java
@@ -21,15 +21,20 @@ import java.util.TreeMap;
 
 public enum ProducerField {
    ID("id"),
-   SESSION("session"),
+   NAME("name"),
+   SESSION("session", "sessionID"),
    CONNECTION_ID("connectionID"),
-   ADDRESS("address"), USER("user"),
+   ADDRESS("address", "destination"),
+   USER("user"),
    VALIDATED_USER("validatedUser"),
    PROTOCOL("protocol"),
    CLIENT_ID("clientID"),
    LOCAL_ADDRESS("localAddress"),
    REMOTE_ADDRESS("remoteAddress"),
-   CREATION_TIME("creationTime");
+   CREATION_TIME("creationTime"),
+   MESSAGE_SENT("msgSent"),
+   MESSAGE_SENT_SIZE("msgSizeSent"),
+   LAST_PRODUCED_MESSAGE_ID("lastProducedMessageID");
 
    private static final Map<String, ProducerField> lookup = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
 
@@ -41,12 +46,27 @@ public enum ProducerField {
 
    private final String name;
 
+   private final String alternativeName;
+
    public String getName() {
       return name;
    }
 
+   /**
+    * There is some inconsistency with some json objects returned for consumers because they were hard coded.
+    * This is just to track the differences and provide backward compatibility.
+    * @return the old alternative name
+    */
+   public String getAlternativeName() {
+      return alternativeName;
+   }
+
    ProducerField(String name) {
+      this(name, "");
+   }
+   ProducerField(String name, String alternativeName) {
       this.name = name;
+      this.alternativeName = alternativeName;
    }
 
    public static ProducerField valueOfName(String name) {
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ProducerView.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ProducerView.java
index cfddf7c65d..76556f0ab6 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ProducerView.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ProducerView.java
@@ -59,6 +59,7 @@ public class ProducerView extends ActiveMQAbstractView<ServerProducer> {
 
       JsonObjectBuilder obj = JsonLoader.createObjectBuilder()
          .add(ProducerField.ID.getName(), toString(producer.getID()))
+         .add(ProducerField.NAME.getName(), toString(producer.getName()))
          .add(ProducerField.SESSION.getName(), toString(session.getName()))
          .add(ProducerField.CLIENT_ID.getName(), toString(sessionClientID))
          .add(ProducerField.USER.getName(), toString(session.getUsername()))
@@ -67,7 +68,10 @@ public class ProducerView extends ActiveMQAbstractView<ServerProducer> {
          .add(ProducerField.ADDRESS.getName(), toString(producer.getAddress() != null ? producer.getAddress() : session.getDefaultAddress()))
          .add(ProducerField.LOCAL_ADDRESS.getName(), toString(session.getRemotingConnection().getTransportConnection().getLocalAddress()))
          .add(ProducerField.REMOTE_ADDRESS.getName(), toString(session.getRemotingConnection().getTransportConnection().getRemoteAddress()))
-         .add(ProducerField.CREATION_TIME.getName(), toString(producer.getCreationTime()));
+         .add(ProducerField.CREATION_TIME.getName(), toString(producer.getCreationTime()))
+         .add(ProducerField.MESSAGE_SENT.getName(), producer.getMessagesSent())
+         .add(ProducerField.MESSAGE_SENT_SIZE.getName(), producer.getMessagesSentSize())
+         .add(ProducerField.LAST_PRODUCED_MESSAGE_ID.getName(), toString(producer.getLastProducedMessageID()));
       return obj;
    }
 
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ConsumerFilterPredicate.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ConsumerFilterPredicate.java
index b42e5a473a..ceb48eeb7a 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ConsumerFilterPredicate.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ConsumerFilterPredicate.java
@@ -59,6 +59,18 @@ public class ConsumerFilterPredicate extends ActiveMQFilterPredicate<ServerConsu
             return matches(server.getSessionByID(consumer.getSessionID()).getRemotingConnection().getTransportConnection().getLocalAddress());
          case REMOTE_ADDRESS:
             return matches(server.getSessionByID(consumer.getSessionID()).getRemotingConnection().getTransportConnection().getRemoteAddress());
+         case MESSAGES_IN_TRANSIT:
+            return matches(consumer.getMessagesInTransit());
+         case MESSAGES_IN_TRANSIT_SIZE:
+            return matches(consumer.getMessagesInTransitSize());
+         case MESSAGES_DELIVERED:
+            return matches(consumer.getDeliveringMessages());
+         case MESSAGES_DELIVERED_SIZE:
+            return matches(consumer.getMessagesDeliveredSize());
+         case MESSAGES_ACKNOWLEDGED:
+            return matches(consumer.getMessagesAcknowledged());
+         case MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT:
+            return matches(consumer.getMessagesAcknowledgedAwaitingCommit());
       }
       return true;
    }
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/ServerPacketDecoder.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/ServerPacketDecoder.java
index 53b784da66..4153e450ac 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/ServerPacketDecoder.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/ServerPacketDecoder.java
@@ -29,11 +29,13 @@ import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.BackupRequ
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.BackupResponseMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ClusterConnectMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ClusterConnectReplyMessage;
+import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.CreateProducerMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.FederationDownstreamConnectMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.MessagePacketI;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.NodeAnnounceMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.QuorumVoteMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.QuorumVoteReplyMessage;
+import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.RemoveProducerMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ReplicationAddMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ReplicationAddTXMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ReplicationCommitMessage;
@@ -58,16 +60,19 @@ import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSen
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendMessage_1X;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendMessage_V2;
+import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionSendMessage_V3;
 import org.apache.activemq.artemis.core.server.LargeServerMessage;
 
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.BACKUP_REQUEST;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.BACKUP_REQUEST_RESPONSE;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.CLUSTER_CONNECT;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.CLUSTER_CONNECT_REPLY;
+import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.CREATE_PRODUCER;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.FEDERATION_DOWNSTREAM_CONNECT;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.NODE_ANNOUNCE;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.QUORUM_VOTE;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.QUORUM_VOTE_REPLY;
+import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.REMOVE_PRODUCER;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.REPLICATION_APPEND;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.REPLICATION_APPEND_TX;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.REPLICATION_COMMIT_ROLLBACK;
@@ -106,8 +111,10 @@ public class ServerPacketDecoder extends ClientPacketDecoder {
          sendMessage = new SessionSendMessage_1X(new CoreMessage(this.coreMessageObjectPools));
       } else if (connection.isVersionBeforeAsyncResponseChange()) {
          sendMessage = new SessionSendMessage(new CoreMessage(this.coreMessageObjectPools));
-      } else {
+      } else if (connection.isBeforeProducerMetricsChanged()) {
          sendMessage = new SessionSendMessage_V2(new CoreMessage(this.coreMessageObjectPools));
+      } else {
+         sendMessage = new SessionSendMessage_V3(new CoreMessage(this.coreMessageObjectPools));
       }
 
       sendMessage.decode(in);
@@ -269,6 +276,14 @@ public class ServerPacketDecoder extends ClientPacketDecoder {
             packet = new FederationDownstreamConnectMessage();
             break;
          }
+         case CREATE_PRODUCER: {
+            packet = new CreateProducerMessage();
+            break;
+         }
+         case REMOVE_PRODUCER: {
+            packet = new RemoveProducerMessage();
+            break;
+         }
          default: {
             packet = super.decode(packetType, connection);
          }
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/core/ServerSessionPacketHandler.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/core/ServerSessionPacketHandler.java
index 7f0a864452..28fea3cd6c 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/core/ServerSessionPacketHandler.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/core/ServerSessionPacketHandler.java
@@ -21,6 +21,7 @@ import javax.transaction.xa.Xid;
 import java.util.List;
 import java.util.Objects;
 
+import io.netty.util.collection.IntObjectHashMap;
 import org.apache.activemq.artemis.api.core.ActiveMQException;
 import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
 import org.apache.activemq.artemis.api.core.ActiveMQIOErrorException;
@@ -31,6 +32,7 @@ import org.apache.activemq.artemis.api.core.Message;
 import org.apache.activemq.artemis.api.core.QueueConfiguration;
 import org.apache.activemq.artemis.api.core.RoutingType;
 import org.apache.activemq.artemis.api.core.SimpleString;
+import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
 import org.apache.activemq.artemis.api.core.client.ClientSession;
 import org.apache.activemq.artemis.core.exception.ActiveMQXAException;
 import org.apache.activemq.artemis.core.io.IOCallback;
@@ -39,12 +41,14 @@ import org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ActiveMQExceptionMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ActiveMQExceptionMessage_V2;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.CreateAddressMessage;
+import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.CreateProducerMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.CreateQueueMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.CreateQueueMessage_V2;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.CreateSharedQueueMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.CreateSharedQueueMessage_V2;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.NullResponseMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.NullResponseMessage_V2;
+import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.RemoveProducerMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.RollbackMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionAcknowledgeMessage;
 import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionAddMetaDataMessage;
@@ -97,6 +101,7 @@ import org.apache.activemq.artemis.core.server.ServerSession;
 import org.apache.activemq.artemis.logs.AuditLogger;
 import org.apache.activemq.artemis.spi.core.protocol.EmbedMessageUtil;
 import org.apache.activemq.artemis.spi.core.remoting.Connection;
+import org.apache.activemq.artemis.utils.UUIDGenerator;
 import org.apache.activemq.artemis.utils.pools.MpscPool;
 import org.apache.activemq.artemis.utils.pools.Pool;
 import org.apache.activemq.artemis.utils.SimpleFuture;
@@ -108,11 +113,13 @@ import org.slf4j.LoggerFactory;
 import java.lang.invoke.MethodHandles;
 
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.CREATE_ADDRESS;
+import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.CREATE_PRODUCER;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.CREATE_QUEUE;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.CREATE_QUEUE_V2;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.CREATE_SHARED_QUEUE;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.CREATE_SHARED_QUEUE_V2;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.DELETE_QUEUE;
+import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.REMOVE_PRODUCER;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.SESS_ACKNOWLEDGE;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.SESS_BINDINGQUERY;
 import static org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl.SESS_CLOSE;
@@ -151,6 +158,8 @@ public class ServerSessionPacketHandler implements ChannelHandler {
 
    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
+   private static final String PRODUCER_ID_PREFIX = "artemis:sender:ID:";
+
    private final ServerSession session;
 
    private final StorageManager storageManager;
@@ -174,6 +183,8 @@ public class ServerSessionPacketHandler implements ChannelHandler {
 
    private final Pool<NullResponseMessage_V2> poolNullResponseV2;
 
+   private final IntObjectHashMap<String> producers = new IntObjectHashMap<>();
+
    public ServerSessionPacketHandler(final ActiveMQServer server,
                                      final ServerSession session,
                                      final Channel channel) {
@@ -323,7 +334,8 @@ public class ServerSessionPacketHandler implements ChannelHandler {
                case SESS_SEND_CONTINUATION: {
                   SessionSendContinuationMessage message = (SessionSendContinuationMessage) packet;
                   requiresResponse = message.isRequiresResponse();
-                  sendContinuations(message.getPacketSize(), message.getMessageBodySize(), message.getBody(), message.isContinues());
+                  int senderID = message.getSenderID();
+                  sendContinuations(message.getPacketSize(), message.getMessageBodySize(), message.getBody(), message.isContinues(), senderID);
                   if (requiresResponse) {
                      response = createNullResponseMessage(packet);
                   }
@@ -635,6 +647,28 @@ public class ServerSessionPacketHandler implements ChannelHandler {
                   }
                   break;
                }
+               case CREATE_PRODUCER: {
+                  CreateProducerMessage message = (CreateProducerMessage) packet;
+                  if (!producers.containsKey(message.getId())) {
+                     // this is used to create/destroy the producer so needs to be unique
+                     String senderName = PRODUCER_ID_PREFIX + UUIDGenerator.getInstance().generateUUID();
+                     producers.put(message.getId(), senderName);
+                     session.addProducer(senderName, ActiveMQClient.DEFAULT_CORE_PROTOCOL, message.getAddress() != null ? message.getAddress().toString() : null);
+                  } else {
+                     ActiveMQServerLogger.LOGGER.producerAlreadyExists(message.getId(),session.getName(), remotingConnection.getRemoteAddress());
+                  }
+                  break;
+               }
+               case REMOVE_PRODUCER: {
+                  RemoveProducerMessage message = (RemoveProducerMessage) packet;
+                  String remove = producers.remove(message.getId());
+                  if (remove != null) {
+                     session.removeProducer(remove);
+                  } else {
+                     ActiveMQServerLogger.LOGGER.producerDoesNotExist(message.getId(), session.getName(), remotingConnection.getRemoteAddress());
+                  }
+                  break;
+               }
             }
          } catch (ActiveMQIOErrorException e) {
             response = onActiveMQIOErrorExceptionWhileHandlePacket(packet, e, requiresResponse, response, this.session);
@@ -747,7 +781,7 @@ public class ServerSessionPacketHandler implements ChannelHandler {
          try {
             final SessionSendMessage message = (SessionSendMessage) packet;
             requiresResponse = message.isRequiresResponse();
-            this.session.send(EmbedMessageUtil.extractEmbedded(message.getMessage(), storageManager), this.direct);
+            this.session.send(EmbedMessageUtil.extractEmbedded(message.getMessage(), storageManager), this.direct, producers.get(message.getSenderID()));
             if (requiresResponse) {
                response = createNullResponseMessage(packet);
             }
@@ -1049,7 +1083,8 @@ public class ServerSessionPacketHandler implements ChannelHandler {
    private void sendContinuations(final int packetSize,
                                   final long messageBodySize,
                                   final byte[] body,
-                                  final boolean continues) throws Exception {
+                                  final boolean continues,
+                                  final int senderID) throws Exception {
 
       synchronized (largeMessageLock) {
          if (currentLargeMessage == null) {
@@ -1071,7 +1106,7 @@ public class ServerSessionPacketHandler implements ChannelHandler {
             LargeServerMessage message = currentLargeMessage;
             currentLargeMessage.setStorageManager(storageManager);
             currentLargeMessage = null;
-            session.doSend(session.getCurrentTransaction(), EmbedMessageUtil.extractEmbedded((ICoreMessage)message.toMessage(), storageManager), null, false, false);
+            session.doSend(session.getCurrentTransaction(), EmbedMessageUtil.extractEmbedded((ICoreMessage)message.toMessage(), storageManager), null, false, producers.get(senderID), false);
          }
       }
    }
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/ActiveMQPacketHandler.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/ActiveMQPacketHandler.java
index 64dd56d196..28c53c4602 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/ActiveMQPacketHandler.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/ActiveMQPacketHandler.java
@@ -45,9 +45,7 @@ import org.apache.activemq.artemis.core.security.ActiveMQPrincipal;
 import org.apache.activemq.artemis.core.server.ActiveMQMessageBundle;
 import org.apache.activemq.artemis.core.server.ActiveMQServer;
 import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
-import org.apache.activemq.artemis.core.server.ServerProducer;
 import org.apache.activemq.artemis.core.server.ServerSession;
-import org.apache.activemq.artemis.core.server.impl.ServerProducerImpl;
 import org.apache.activemq.artemis.core.version.Version;
 import org.apache.activemq.artemis.logs.AuditLogger;
 import org.slf4j.Logger;
@@ -183,9 +181,8 @@ public class ActiveMQPacketHandler implements ChannelHandler {
          Map<SimpleString, RoutingType> routingTypeMap = protocolManager.getPrefixes();
 
          CoreSessionCallback sessionCallback = new CoreSessionCallback(request.getName(), protocolManager, channel, connection);
-         ServerSession session = server.createSession(request.getName(), activeMQPrincipal == null ? request.getUsername() : activeMQPrincipal.getUserName(), activeMQPrincipal == null ? request.getPassword() : activeMQPrincipal.getPassword(), request.getMinLargeMessageSize(), connection, request.isAutoCommitSends(), request.isAutoCommitAcks(), request.isPreAcknowledge(), request.isXA(), request.getDefaultAddress(), sessionCallback, true, sessionOperationContext, routingTypeMap, protocolM [...]
-         ServerProducer serverProducer = new ServerProducerImpl(session.getName(), "CORE", request.getDefaultAddress());
-         session.addProducer(serverProducer);
+         boolean isLegacyProducer = request.getVersion() < PacketImpl.ARTEMIS_2_28_0_VERSION;
+         ServerSession session = server.createSession(request.getName(), activeMQPrincipal == null ? request.getUsername() : activeMQPrincipal.getUserName(), activeMQPrincipal == null ? request.getPassword() : activeMQPrincipal.getPassword(), request.getMinLargeMessageSize(), connection, request.isAutoCommitSends(), request.isAutoCommitAcks(), request.isPreAcknowledge(), request.isXA(), request.getDefaultAddress(), sessionCallback, true, sessionOperationContext, routingTypeMap, protocolM [...]
          ServerSessionPacketHandler handler = new ServerSessionPacketHandler(server, session, channel);
          channel.setHandler(handler);
          sessionCallback.setSessionHandler(handler);
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java
index 2f690afa8d..97031c2df6 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java
@@ -349,7 +349,9 @@ public interface ActiveMQServer extends ServiceComponent {
                                boolean autoCreateQueues,
                                OperationContext context,
                                Map<SimpleString, RoutingType> prefixes,
-                               String securityDomain, String validatedUser) throws Exception;
+                               String securityDomain,
+                               String validatedUser,
+                               boolean isLegacyProducer) throws Exception;
 
    /** This is to be used in places where security is bypassed, like internal sessions, broker connections, etc... */
    ServerSession createInternalSession(String name,
@@ -364,7 +366,8 @@ public interface ActiveMQServer extends ServiceComponent {
                                boolean autoCreateQueues,
                                OperationContext context,
                                Map<SimpleString, RoutingType> prefixes,
-                               String securityDomain) throws Exception;
+                               String securityDomain,
+                               boolean isLegacyProducer) throws Exception;
 
    /** should the server rebuild page counters upon startup.
     *  this will be useful on testing or an embedded broker scenario */
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java
index 2b9699df52..eaec474036 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java
@@ -1220,7 +1220,11 @@ public interface ActiveMQServerLogger {
    @LogMessage(id = 222308, value = "Unable to listen for incoming fail-back request because {} is null. Ensure the broker has the proper cluster-connection configuration.", level = LogMessage.Level.WARN)
    void failBackCheckerFailure(String component);
 
+   @LogMessage(id = 222309, value = "Trying to remove a producer with ID {} that doesnt exist from session {} on Connection {}.", level = LogMessage.Level.WARN)
+   void producerDoesNotExist(int id, String session, String remoteAddress);
 
+   @LogMessage(id = 222310, value = "Trying to add a producer with ID {} that already exists to session {} on Connection {}.", level = LogMessage.Level.WARN)
+   void producerAlreadyExists(int id, String session, String remoteAddress);
 
    @LogMessage(id = 224000, value = "Failure in initialisation", level = LogMessage.Level.ERROR)
    void initializationError(Throwable e);
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ConsumerInfo.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ConsumerInfo.java
index 23642565b4..3ac36b3ef7 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ConsumerInfo.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ConsumerInfo.java
@@ -62,4 +62,51 @@ public interface ConsumerInfo {
     */
    String getConnectionRemoteAddress();
 
+   /**
+    * Returns how many messages are out for delivery but not yet acknowledged
+    * @return delivering count
+    */
+   int getMessagesInTransit();
+
+   /**
+    * Returns the combined size of all the messages out for delivery but not yet acknowledged
+    * @return the total size of all the messages
+    */
+   long getMessagesInTransitSize();
+
+   /**
+    * Returns The total number of messages sent to a consumer including redeliveries that have been acknowledged
+    * @return the total number of messages delivered.
+    */
+   long getMessagesDelivered();
+
+   /**
+    * Returns the total size of all the messages delivered to the consumer. This includes redelivered messages
+    * @return The total size of all the messages
+    */
+   long getMessagesDeliveredSize();
+
+   /**
+    * Returns the number of messages acknowledged by this consumer since it was created
+    * @return messages acknowledged
+    */
+   long getMessagesAcknowledged();
+
+   /**
+    * Returns the number of acknowledged messages that are awaiting commit in a transaction
+    * @return th eno acknowledgements awaiting commit
+    */
+   int getMessagesAcknowledgedAwaitingCommit();
+
+   /**
+    * Returns the time in milliseconds that the last message was delivered to a consumer
+    * @return the time of the last message delivered
+    */
+   long getLastDeliveredTime();
+
+   /**
+    * Returns the time in milliseconds that the last message was acknowledged by a consumer
+    * @return the time of the last message was acknowledged
+    */
+   long getLastAcknowledgedTime();
 }
\ No newline at end of file
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerConsumer.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerConsumer.java
index e743c0401c..646df6a787 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerConsumer.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerConsumer.java
@@ -110,4 +110,11 @@ public interface ServerConsumer extends Consumer, ConsumerInfo {
    long getCreationTime();
 
    String getSessionID();
+
+   /**
+    * This is needed when some protocols (OW) handle the acks themselves and need to update the metrics
+    * @param ref the message reference
+    * @param transaction the tx
+    */
+   void metricsAcknowledge(MessageReference ref, Transaction transaction);
 }
\ No newline at end of file
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerProducer.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerProducer.java
index 97f8fe52d4..64abf8eed7 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerProducer.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerProducer.java
@@ -17,7 +17,12 @@
 package org.apache.activemq.artemis.core.server;
 
 public interface ServerProducer {
-   String getAddress();
+   String ANONYMOUS = "ANONYMOUS";
+
+   long getID();
+
+   String getName();
+   String getAddress();;
 
    String getProtocol();
 
@@ -29,7 +34,14 @@ public interface ServerProducer {
 
    String getConnectionID();
 
-   String getID();
 
    long getCreationTime();
+
+   Object getLastProducedMessageID();
+
+   long getMessagesSent();
+
+   long getMessagesSentSize();
+
+   void updateMetrics(Object lastProducedMessageID, int encodeSize);
 }
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerSession.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerSession.java
index f238a4925d..2d880f1ec8 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerSession.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerSession.java
@@ -18,6 +18,7 @@ package org.apache.activemq.artemis.core.server;
 
 import org.apache.activemq.artemis.json.JsonArrayBuilder;
 import javax.transaction.xa.Xid;
+import java.util.Collection;
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
@@ -332,11 +333,13 @@ public interface ServerSession extends SecurityAuth {
    RoutingStatus send(Transaction tx,
                       Message message,
                       boolean direct,
+                      String senderName,
                       boolean noAutoCreateQueue) throws Exception;
 
    RoutingStatus send(Transaction tx,
                       Message message,
                       boolean direct,
+                      String senderName,
                       boolean noAutoCreateQueue,
                       RoutingContext routingContext) throws Exception;
 
@@ -345,18 +348,20 @@ public interface ServerSession extends SecurityAuth {
                         Message msg,
                         SimpleString originalAddress,
                         boolean direct,
+                        String senderName,
                         boolean noAutoCreateQueue) throws Exception;
 
    RoutingStatus doSend(Transaction tx,
                         Message msg,
                         SimpleString originalAddress,
                         boolean direct,
+                        String senderName,
                         boolean noAutoCreateQueue,
                         RoutingContext routingContext) throws Exception;
 
-   RoutingStatus send(Message message, boolean direct, boolean noAutoCreateQueue) throws Exception;
+   RoutingStatus send(Message message, boolean direct, String senderName, boolean noAutoCreateQueue) throws Exception;
 
-   RoutingStatus send(Message message, boolean direct) throws Exception;
+   RoutingStatus send(Message message, boolean direct, String senderName) throws Exception;
 
    void forceConsumerDelivery(long consumerID, long sequence) throws Exception;
 
@@ -376,8 +381,6 @@ public interface ServerSession extends SecurityAuth {
 
    Map<String, String> getMetaData();
 
-   String[] getTargetAddresses();
-
    /**
     * Add all the producers detail to the JSONArray object.
     * This is a method to be used by the management layer.
@@ -387,7 +390,6 @@ public interface ServerSession extends SecurityAuth {
     */
    void describeProducersInfo(JsonArrayBuilder objs) throws Exception;
 
-   String getLastSentMessageID(String address);
 
    long getCreationTime();
 
@@ -522,11 +524,11 @@ public interface ServerSession extends SecurityAuth {
    Pair<SimpleString, EnumSet<RoutingType>> getAddressAndRoutingTypes(SimpleString address,
                                                                       EnumSet<RoutingType> defaultRoutingTypes);
 
-   void addProducer(ServerProducer serverProducer);
+   void addProducer(String name, String protocol, String address);
 
    void removeProducer(String ID);
 
-   Map<String, ServerProducer> getServerProducers();
+   Collection<ServerProducer> getServerProducers();
 
    String getDefaultAddress();
 
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
index 9e122d670e..2a313ce4a2 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
@@ -1746,7 +1746,8 @@ public class ActiveMQServerImpl implements ActiveMQServer {
                                       final OperationContext context,
                                       final Map<SimpleString, RoutingType> prefixes,
                                       final String securityDomain,
-                                      String validatedUser) throws Exception {
+                                      String validatedUser,
+                                      boolean isLegacyProducer) throws Exception {
       if (validatedUser == null) {
          validatedUser = validateUser(username, password, connection, securityDomain);
       }
@@ -1758,7 +1759,7 @@ public class ActiveMQServerImpl implements ActiveMQServer {
                                        autoCommitAcks, preAcknowledge, xa, defaultAddress, callback, autoCreateQueues, prefixes);
       }
 
-      final ServerSessionImpl session = internalCreateSession(name, username, password, validatedUser, minLargeMessageSize, connection, autoCommitSends, autoCommitAcks, preAcknowledge, xa, defaultAddress, callback, context, autoCreateQueues, prefixes, securityDomain);
+      final ServerSessionImpl session = internalCreateSession(name, username, password, validatedUser, minLargeMessageSize, connection, autoCommitSends, autoCommitAcks, preAcknowledge, xa, defaultAddress, callback, context, autoCreateQueues, prefixes, securityDomain, isLegacyProducer);
 
       return session;
    }
@@ -1786,8 +1787,9 @@ public class ActiveMQServerImpl implements ActiveMQServer {
                                        boolean autoCreateQueues,
                                        OperationContext context,
                                        Map<SimpleString, RoutingType> prefixes,
-                                       String securityDomain) throws Exception {
-      ServerSessionImpl session = internalCreateSession(name, null, null, null, minLargeMessageSize, connection, autoCommitSends, autoCommitAcks, preAcknowledge, xa, defaultAddress, callback, context, autoCreateQueues, prefixes, securityDomain);
+                                       String securityDomain,
+                                       boolean isLegacyProducer) throws Exception {
+      ServerSessionImpl session = internalCreateSession(name, null, null, null, minLargeMessageSize, connection, autoCommitSends, autoCommitAcks, preAcknowledge, xa, defaultAddress, callback, context, autoCreateQueues, prefixes, securityDomain, isLegacyProducer);
       session.disableSecurity();
       return session;
    }
@@ -1864,14 +1866,15 @@ public class ActiveMQServerImpl implements ActiveMQServer {
                                                      OperationContext context,
                                                      boolean autoCreateQueues,
                                                      Map<SimpleString, RoutingType> prefixes,
-                                                     String securityDomain) throws Exception {
+                                                     String securityDomain,
+                                                     boolean isLegacyProducer) throws Exception {
 
       if (hasBrokerSessionPlugins()) {
          callBrokerSessionPlugins(plugin -> plugin.beforeCreateSession(name, username, minLargeMessageSize, connection,
                                                                        autoCommitSends, autoCommitAcks, preAcknowledge, xa, defaultAddress, callback, autoCreateQueues, context, prefixes));
       }
 
-      ServerSessionImpl session = new ServerSessionImpl(name, username, password, validatedUser, minLargeMessageSize, autoCommitSends, autoCommitAcks, preAcknowledge, configuration.isPersistDeliveryCountBeforeDelivery(), xa, connection, storageManager, postOffice, resourceManager, securityStore, managementService, this, configuration.getManagementAddress(), defaultAddress == null ? null : new SimpleString(defaultAddress), callback, context, pagingManager, prefixes, securityDomain);
+      ServerSessionImpl session = new ServerSessionImpl(name, username, password, validatedUser, minLargeMessageSize, autoCommitSends, autoCommitAcks, preAcknowledge, configuration.isPersistDeliveryCountBeforeDelivery(), xa, connection, storageManager, postOffice, resourceManager, securityStore, managementService, this, configuration.getManagementAddress(), defaultAddress == null ? null : new SimpleString(defaultAddress), callback, context, pagingManager, prefixes, securityDomain, isLega [...]
 
       sessions.put(name, session);
 
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerConsumerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerConsumerImpl.java
index e8ed25652b..d75a939336 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerConsumerImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerConsumerImpl.java
@@ -26,7 +26,9 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicLongFieldUpdater;
 import java.util.function.Function;
 
 import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
@@ -61,6 +63,8 @@ import org.apache.activemq.artemis.core.server.SlowConsumerDetectionListener;
 import org.apache.activemq.artemis.core.server.management.ManagementService;
 import org.apache.activemq.artemis.core.server.management.Notification;
 import org.apache.activemq.artemis.core.transaction.Transaction;
+import org.apache.activemq.artemis.core.transaction.TransactionOperationAbstract;
+import org.apache.activemq.artemis.core.transaction.TransactionPropertyIndexes;
 import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
 import org.apache.activemq.artemis.logs.AuditLogger;
 import org.apache.activemq.artemis.spi.core.protocol.SessionCallback;
@@ -153,14 +157,14 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
 
    private AtomicLong messageConsumedSnapshot = new AtomicLong(0);
 
-   private long acks;
-
    private boolean requiresLegacyPrefix = false;
 
    private boolean anycast = false;
 
    private boolean isClosed = false;
 
+   ServerConsumerMetrics metrics = new ServerConsumerMetrics();
+
 
    public ServerConsumerImpl(final long id,
                              final ServerSession session,
@@ -355,6 +359,11 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
       return this.session.getName();
    }
 
+   @Override
+   public void metricsAcknowledge(MessageReference ref, Transaction transaction) {
+      metrics.addAcknowledge(ref.getMessage().getEncodeSize(), transaction);
+   }
+
    @Override
    public List<MessageReference> getDeliveringMessages() {
       synchronized (lock) {
@@ -441,6 +450,8 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
                deliveringRefs.add(ref);
             }
 
+            metrics.addMessage(ref.getMessage().getEncodeSize());
+
             ref.handled();
 
             ref.setConsumerId(this.id);
@@ -466,7 +477,7 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
             if (preAcknowledge) {
                // With pre-ack, we ack *before* sending to the client
                ref.getQueue().acknowledge(ref, this);
-               acks++;
+               metrics.addAcknowledge(ref.getMessage().getEncodeSize(), null);
             }
 
          }
@@ -704,9 +715,9 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
          final List<MessageReference> refs = new ArrayList<>(deliveringRefs.size());
          MessageReference ref;
          while ((ref = deliveringRefs.poll()) != null) {
+            metrics.addAcknowledge(ref.getMessage().getEncodeSize(), tx);
             if (performACK) {
                ref.acknowledge(tx, this);
-
                performACK = false;
             } else {
                refs.add(ref);
@@ -911,8 +922,7 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
 
             ref.acknowledge(tx, this);
             ackedRefs.add(ref.getMessageID());
-
-            acks++;
+            metrics.addAcknowledge(ref.getMessage().getEncodeSize(), tx);
          }
          while (ref.getMessageID() != messageID);
 
@@ -973,11 +983,9 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
             tx.markAsRollbackOnly(ils);
             throw ils;
          }
-
+         metrics.addAcknowledge(ref.getMessage().getEncodeSize(), tx);
          ref.acknowledge(tx, this);
 
-         acks++;
-
          if (startedTransaction) {
             tx.commit();
          }
@@ -1016,7 +1024,7 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
       if (!failed) {
          ref.decrementDeliveryCount();
       }
-
+      metrics.addAcknowledge(ref.getMessage().getEncodeSize(), null);
       ref.getQueue().cancel(ref, System.currentTimeMillis());
    }
 
@@ -1032,7 +1040,7 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
       if (ref == null) {
          return; // nothing to be done
       }
-
+      metrics.addAcknowledge(ref.getMessage().getEncodeSize(), null);
       ref.getQueue().sendToDeadLetterAddress(null, ref);
    }
 
@@ -1040,6 +1048,7 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
    public synchronized void backToDelivering(MessageReference reference) {
       synchronized (lock) {
          deliveringRefs.addFirst(reference);
+         metrics.addMessage(reference.getMessage().getEncodeSize());
       }
    }
 
@@ -1059,10 +1068,12 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
          }
 
          if (deliveringRefs.peek().getMessage().getMessageID() == messageID) {
-            return deliveringRefs.poll();
+            MessageReference ref = deliveringRefs.poll();
+            return ref;
          }
          //slow path in a separate method
-         return removeDeliveringRefById(messageID);
+         MessageReference ref = removeDeliveringRefById(messageID);
+         return ref;
       }
    }
 
@@ -1114,6 +1125,7 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
 
    public float getRate() {
       float timeSlice = ((System.currentTimeMillis() - consumerRateCheckTime.getAndSet(System.currentTimeMillis())) / 1000.0f);
+      long acks = metrics.getMessagesAcknowledged();
       if (timeSlice == 0) {
          messageConsumedSnapshot.getAndSet(acks);
          return 0.0f;
@@ -1513,7 +1525,143 @@ public class ServerConsumerImpl implements ServerConsumer, ReadyListener {
       return this.session.getRemotingConnection().getTransportConnection().getRemoteAddress();
    }
 
+   @Override
+   public long getMessagesInTransitSize() {
+      return metrics.getMessagesInTransitSize();
+   }
+
+   @Override
+   public int getMessagesInTransit() {
+      return deliveringRefs.size();
+   }
+
+   @Override
+   public long getLastDeliveredTime() {
+      return metrics.getLastDeliveredTime();
+   }
+
+   @Override
+   public long getLastAcknowledgedTime() {
+      return metrics.getLastAcknowledgedTime();
+   }
+
+   @Override
+   public long getMessagesAcknowledged() {
+      return metrics.getMessagesAcknowledged();
+   }
+
+   @Override
+   public long getMessagesDeliveredSize() {
+      return metrics.getMessagesDeliveredSize();
+   }
+
+   @Override
+   public long getMessagesDelivered() {
+      return metrics.getMessagesDelivered();
+   }
+
+   @Override
+   public int getMessagesAcknowledgedAwaitingCommit() {
+      return metrics.getMessagesAcknowledgedAwaitingCommit();
+   }
+
    public SessionCallback getCallback() {
       return callback;
    }
+
+   static class ServerConsumerMetrics extends TransactionOperationAbstract {
+
+      /**
+       * Since messages can be delivered (incremented) and acknowledged (decremented) at the same time we have to protect
+       * the encode size and make it atomic. The other fields are ok since they are only accessed from a single thread.
+       */
+      private static final AtomicLongFieldUpdater<ServerConsumerMetrics> messagesInTransitSizeUpdater = AtomicLongFieldUpdater.newUpdater(ServerConsumerMetrics.class, "messagesInTransitSize");
+
+      private volatile long messagesInTransitSize = 0;
+
+      private static final AtomicIntegerFieldUpdater<ServerConsumerMetrics> messagesAcknowledgedAwaitingCommitUpdater = AtomicIntegerFieldUpdater.newUpdater(ServerConsumerMetrics.class, "messagesAcknowledgedAwaitingCommit");
+
+      private volatile int messagesAcknowledgedAwaitingCommit = 0;
+
+      private static final AtomicLongFieldUpdater<ServerConsumerMetrics>messagesDeliveredSizeUpdater = AtomicLongFieldUpdater.newUpdater(ServerConsumerMetrics.class, "messagesDeliveredSize");
+
+      private volatile long messagesDeliveredSize = 0;
+
+      private volatile long lastDeliveredTime = 0;
+
+      private volatile long lastAcknowledgedTime = 0;
+
+      private static final AtomicLongFieldUpdater<ServerConsumerMetrics>messagesDeliveredUpdater = AtomicLongFieldUpdater.newUpdater(ServerConsumerMetrics.class, "messagesDelivered");
+
+      private volatile long messagesDelivered = 0;
+
+      private static final AtomicLongFieldUpdater<ServerConsumerMetrics> messagesAcknowledgedUpdater = AtomicLongFieldUpdater.newUpdater(ServerConsumerMetrics.class, "messagesAcknowledged");
+
+      private volatile long messagesAcknowledged = 0;
+
+
+      public long getMessagesInTransitSize() {
+         return messagesInTransitSizeUpdater.get(this);
+      }
+
+      public long getMessagesDeliveredSize() {
+         return messagesDeliveredSizeUpdater.get(this);
+      }
+
+      public long getLastDeliveredTime() {
+         return lastDeliveredTime;
+      }
+
+      public long getLastAcknowledgedTime() {
+         return lastAcknowledgedTime;
+      }
+
+      public long getMessagesDelivered() {
+         return messagesDeliveredUpdater.get(this);
+      }
+
+      public long getMessagesAcknowledged() {
+         return messagesAcknowledgedUpdater.get(this);
+      }
+
+      public int getMessagesAcknowledgedAwaitingCommit() {
+         return messagesAcknowledgedAwaitingCommitUpdater.get(this);
+      }
+
+      public void addMessage(int encodeSize) {
+         messagesInTransitSizeUpdater.addAndGet(this, encodeSize);
+         messagesDeliveredSizeUpdater.addAndGet(this, encodeSize);
+         messagesDeliveredUpdater.addAndGet(this, 1);
+         lastDeliveredTime = System.currentTimeMillis();
+      }
+
+      public void addAcknowledge(int encodeSize, Transaction tx) {
+         messagesInTransitSizeUpdater.addAndGet(this, -encodeSize);
+         messagesAcknowledgedUpdater.addAndGet(this, 1);
+         lastAcknowledgedTime = System.currentTimeMillis();
+         if (tx != null) {
+            addOperation(tx);
+            messagesAcknowledgedAwaitingCommitUpdater.addAndGet(this, 1);
+         }
+      }
+
+      @Override
+      public void afterCommit(Transaction tx) {
+         messagesAcknowledgedAwaitingCommitUpdater.set(this, 0);
+      }
+
+
+      @Override
+      public void afterRollback(Transaction tx) {
+         messagesAcknowledgedAwaitingCommitUpdater.set(this, 0);
+      }
+
+      public void addOperation(Transaction tx) {
+         Object property = tx.getProperty(TransactionPropertyIndexes.CONSUMER_METRICS_OPERATION);
+         if (property == null) {
+            tx.putProperty(TransactionPropertyIndexes.CONSUMER_METRICS_OPERATION, this);
+            tx.addOperation(this);
+         }
+      }
+   }
 }
\ No newline at end of file
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerLegacyProducersImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerLegacyProducersImpl.java
new file mode 100644
index 0000000000..e1ab46561a
--- /dev/null
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerLegacyProducersImpl.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.core.server.impl;
+
+import org.apache.activemq.artemis.api.core.Message;
+import org.apache.activemq.artemis.core.server.ServerProducer;
+import org.apache.activemq.artemis.core.server.ServerSession;
+import org.apache.activemq.artemis.utils.collections.MaxSizeMap;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ServerLegacyProducersImpl implements ServerProducers {
+
+   private static final int MAX_PRODUCER_METRIC_SIZE = 100;
+
+   protected final Map<String, ServerProducer> producers = Collections.synchronizedMap(new MaxSizeMap<>(MAX_PRODUCER_METRIC_SIZE));
+   private final String sessionName;
+
+   private final String connectionID;
+
+   public ServerLegacyProducersImpl(ServerSession session) {
+      this.sessionName = session.getName();
+      this.connectionID = session.getConnectionID() != null ? session.getConnectionID().toString() : null;
+   }
+
+   @Override
+   public Map<String, ServerProducer> cloneProducers() {
+      return new HashMap<>(producers);
+   }
+
+   @Override
+   public Collection<ServerProducer> getServerProducers() {
+      return new ArrayList<>(producers.values());
+   }
+
+   @Override
+   public ServerProducer getServerProducer(String senderName, Message msg, ServerSessionImpl serverSession) {
+      String address = msg.getAddress();
+      String name = sessionName + ":" + address;
+      ServerProducer producer = producers.get(name);
+      if (producer == null) {
+         producer = new ServerProducerImpl(name, "CORE", address);
+         producer.setSessionID(sessionName);
+         producer.setConnectionID(connectionID);
+         producers.put(name, producer);
+      }
+      return producer;
+   }
+
+   @Override
+   public void put(String id, ServerProducer producer) {
+      //never called as we track by address the old way
+   }
+
+   @Override
+   public void remove(String id) {
+      //never called as we track by address the old way
+   }
+
+   @Override
+   public void clear() {
+      producers.clear();
+   }
+
+}
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducerImpl.java
index bc0f910484..cb7eef011d 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducerImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducerImpl.java
@@ -18,23 +18,50 @@ package org.apache.activemq.artemis.core.server.impl;
 
 import org.apache.activemq.artemis.core.server.ServerProducer;
 
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicLongFieldUpdater;
+
 public class ServerProducerImpl implements ServerProducer {
-   private final String ID;
+
+   private static final AtomicLong PRODUCER_ID_GENERATOR = new AtomicLong();
+
+   private final long ID;
+   private final String name;
    private final String protocol;
    private final long creationTime;
+   private volatile long messagesSent = 0;
+   private volatile long messagesSentSize = 0;
+
+   private static final AtomicLongFieldUpdater<ServerProducerImpl> messagesSentUpdater = AtomicLongFieldUpdater.newUpdater(ServerProducerImpl.class, "messagesSent");
 
+   private static final AtomicLongFieldUpdater<ServerProducerImpl> messagesSentSizeUpdater = AtomicLongFieldUpdater.newUpdater(ServerProducerImpl.class, "messagesSentSize");
 
    private final String address;
+
+   private volatile Object lastProducedMessageID;
+
    private String sessionID;
+
    private String connectionID;
 
-   public ServerProducerImpl(String ID, String protocol, String address) {
-      this.ID = ID;
+   public ServerProducerImpl(String name, String protocol, String address) {
+      this.ID = PRODUCER_ID_GENERATOR.incrementAndGet();
+      this.name = name;
       this.protocol = protocol;
       this.address = address;
       this.creationTime = System.currentTimeMillis();
    }
 
+   @Override
+   public long getID() {
+      return ID;
+   }
+
+   @Override
+   public String getName() {
+      return name;
+   }
+
    @Override
    public String getAddress() {
       return address;
@@ -52,7 +79,6 @@ public class ServerProducerImpl implements ServerProducer {
 
    @Override
    public void setConnectionID(String connectionID) {
-
       this.connectionID = connectionID;
    }
 
@@ -67,12 +93,29 @@ public class ServerProducerImpl implements ServerProducer {
    }
 
    @Override
-   public String getID() {
-      return ID;
+   public long getCreationTime() {
+      return creationTime;
    }
 
    @Override
-   public long getCreationTime() {
-      return creationTime;
+   public void updateMetrics(Object lastProducedMessageID, int encodeSize) {
+      messagesSentUpdater.addAndGet(this, 1);
+      messagesSentSizeUpdater.getAndAdd(this, encodeSize);
+      this.lastProducedMessageID = lastProducedMessageID;
+   }
+
+   @Override
+   public Object getLastProducedMessageID() {
+      return lastProducedMessageID;
+   }
+
+   @Override
+   public long getMessagesSent() {
+      return messagesSent;
+   }
+
+   @Override
+   public long getMessagesSentSize() {
+      return messagesSentSize;
    }
 }
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/TransactionPropertyIndexes.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducers.java
similarity index 59%
copy from artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/TransactionPropertyIndexes.java
copy to artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducers.java
index 4ba31eeb47..99f79010fc 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/TransactionPropertyIndexes.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducers.java
@@ -14,25 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.activemq.artemis.core.transaction;
+package org.apache.activemq.artemis.core.server.impl;
 
-public class TransactionPropertyIndexes {
+import org.apache.activemq.artemis.api.core.Message;
+import org.apache.activemq.artemis.core.server.ServerProducer;
 
-   public static final int LARGE_MESSAGE_CONFIRMATIONS = 1;
+import java.util.Collection;
+import java.util.Map;
 
-   public static final int PAGE_SYNC = 2;
+public interface ServerProducers {
+   Map<String, ServerProducer> cloneProducers();
 
-   public static final int PAGE_COUNT_INC = 3;
+   Collection<ServerProducer> getServerProducers();
 
-   public static final int PAGE_TRANSACTION_UPDATE = 4;
+   ServerProducer getServerProducer(String senderName, Message msg, ServerSessionImpl serverSession);
 
-   public static final int PAGE_TRANSACTION = 5;
+   void put(String id, ServerProducer producer);
 
-   public static final int REFS_OPERATION = 6;
+   void remove(String id);
 
-   public static final int PAGE_DELIVERY = 7;
-
-   public static final int PAGE_CURSOR_POSITIONS = 8;
-
-   public static final int EXPIRY_LOGGER = 9;
+   void clear();
 }
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducersImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducersImpl.java
new file mode 100644
index 0000000000..ca8561e326
--- /dev/null
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducersImpl.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.core.server.impl;
+
+import org.apache.activemq.artemis.api.core.Message;
+import org.apache.activemq.artemis.core.server.ServerProducer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class ServerProducersImpl implements ServerProducers {
+   protected final Map<String, ServerProducer> producers = new ConcurrentHashMap<>();
+
+   @Override
+   public Map<String, ServerProducer> cloneProducers() {
+      return new HashMap<>(producers);
+   }
+
+   @Override
+   public Collection<ServerProducer> getServerProducers() {
+      return new ArrayList<>(producers.values());
+   }
+
+   @Override
+   public ServerProducer getServerProducer(String senderName, Message msg, ServerSessionImpl serverSession) {
+      if (senderName != null) {
+         return producers.get(senderName);
+      }
+      return null;
+   }
+
+   @Override
+   public void put(String id, ServerProducer producer) {
+      producers.put(id, producer);
+   }
+
+   @Override
+   public void remove(String id) {
+      producers.remove(id);
+   }
+
+   @Override
+   public void clear() {
+      producers.clear();
+   }
+}
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java
index af27a0e8ad..ce02f88e2f 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java
@@ -16,6 +16,7 @@
  */
 package org.apache.activemq.artemis.core.server.impl;
 
+import org.apache.activemq.artemis.core.management.impl.view.ProducerField;
 import org.apache.activemq.artemis.api.core.ActiveMQAddressExistsException;
 import org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException;
 import org.apache.activemq.artemis.core.postoffice.Bindings;
@@ -25,17 +26,16 @@ import java.security.cert.X509Certificate;
 import javax.transaction.xa.XAException;
 import javax.transaction.xa.Xid;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.activemq.artemis.Closeable;
 import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
@@ -102,7 +102,6 @@ import org.apache.activemq.artemis.utils.ByteUtil;
 import org.apache.activemq.artemis.utils.CompositeAddress;
 import org.apache.activemq.artemis.utils.JsonLoader;
 import org.apache.activemq.artemis.utils.PrefixUtil;
-import org.apache.activemq.artemis.utils.collections.MaxSizeMap;
 import org.apache.activemq.artemis.utils.collections.TypedProperties;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -115,7 +114,6 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
 
    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-
    private boolean securityEnabled = true;
 
    private final String securityDomain;
@@ -140,7 +138,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
 
    protected final Map<Long, ServerConsumer> consumers = new ConcurrentHashMap<>();
 
-   protected final Map<String, ServerProducer> producers = new ConcurrentHashMap<>();
+   protected final ServerProducers serverProducers;
 
    protected Transaction tx;
 
@@ -184,9 +182,6 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
 
    private final OperationContext context;
 
-   // Session's usage should be by definition single threaded, hence it's not needed to use a concurrentHashMap here
-   protected final Map<SimpleString, Pair<Object, AtomicLong>> targetAddressInfos = new MaxSizeMap<>(100);
-
    private final long creationTime = System.currentTimeMillis();
 
    // to prevent session from being closed twice.
@@ -228,7 +223,8 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
                             final OperationContext context,
                             final PagingManager pagingManager,
                             final Map<SimpleString, RoutingType> prefixes,
-                            final String securityDomain) throws Exception {
+                            final String securityDomain,
+                            boolean isLegacyProducer) throws Exception {
       this.username = username;
 
       this.password = password;
@@ -289,6 +285,11 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
       sendSessionNotification(CoreNotificationType.SESSION_CREATED);
 
       this.securityDomain = securityDomain;
+      if (isLegacyProducer) {
+         serverProducers = new ServerLegacyProducersImpl(this);
+      } else {
+         serverProducers = new ServerProducersImpl();
+      }
    }
 
    // ServerSession implementation ---------------------------------------------------------------------------
@@ -450,7 +451,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
       }
 
       consumers.clear();
-      producers.clear();
+      serverProducers.clear();
 
       if (closeables != null) {
          for (Closeable closeable : closeables) {
@@ -1186,10 +1187,6 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
 
          remotingConnection.removeFailureListener(cleaner);
       }
-
-      if (server.getAddressInfo(unPrefixedQueueName) == null) {
-         targetAddressInfos.remove(queueToDelete);
-      }
    }
 
    @Override
@@ -1790,29 +1787,32 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
 
 
    @Override
-   public RoutingStatus send(final Message message, final boolean direct) throws Exception {
-      return send(message, direct, false);
+   public RoutingStatus send(final Message message, final boolean direct, final String senderName) throws Exception {
+      return send(message, direct, senderName,false);
    }
 
    @Override
    public RoutingStatus send(final Message message,
                              final boolean direct,
+                             final String senderName,
                              boolean noAutoCreateQueue) throws Exception {
-      return send(getCurrentTransaction(), message, direct, noAutoCreateQueue);
+      return send(getCurrentTransaction(), message, direct, senderName, noAutoCreateQueue);
    }
 
    @Override
    public synchronized RoutingStatus send(Transaction tx,
                                           Message msg,
                                           final boolean direct,
+                                          final String senderName,
                                           boolean noAutoCreateQueue) throws Exception {
-      return send(tx, msg, direct, noAutoCreateQueue, routingContext);
+      return send(tx, msg, direct, senderName, noAutoCreateQueue, routingContext);
    }
 
    @Override
    public synchronized RoutingStatus send(Transaction tx,
                                           Message messageParameter,
                                           final boolean direct,
+                                          final String senderName,
                                           boolean noAutoCreateQueue,
                                           RoutingContext routingContext) throws Exception {
       final Message message = LargeServerMessageImpl.checkLargeMessage(messageParameter, storageManager);
@@ -1865,7 +1865,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
 
             result = handleManagementMessage(tx, message, direct);
          } else {
-            result = doSend(tx, message, address, direct, noAutoCreateQueue, routingContext);
+            result = doSend(tx, message, address, direct, senderName, noAutoCreateQueue, routingContext);
          }
 
          if (AuditLogger.isMessageLoggingEnabled()) {
@@ -1975,30 +1975,6 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
       return metaData;
    }
 
-   @Override
-   public String[] getTargetAddresses() {
-      Map<SimpleString, Pair<Object, AtomicLong>> copy = cloneTargetAddresses();
-      Iterator<SimpleString> iter = copy.keySet().iterator();
-      int num = copy.keySet().size();
-      String[] addresses = new String[num];
-      int i = 0;
-      while (iter.hasNext()) {
-         addresses[i] = iter.next().toString();
-         i++;
-      }
-      return addresses;
-   }
-
-   @Override
-   public String getLastSentMessageID(String address) {
-      Pair<Object, AtomicLong> value = targetAddressInfos.get(SimpleString.toSimpleString(address));
-      if (value != null) {
-         return value.getA().toString();
-      } else {
-         return null;
-      }
-   }
-
    @Override
    public long getCreationTime() {
       return this.creationTime;
@@ -2010,14 +1986,22 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
 
    @Override
    public void describeProducersInfo(JsonArrayBuilder array) throws Exception {
-      Map<SimpleString, Pair<Object, AtomicLong>> targetCopy = cloneTargetAddresses();
-
-      for (Map.Entry<SimpleString, Pair<Object, AtomicLong>> entry : targetCopy.entrySet()) {
+      Map<String, ServerProducer> targetCopy = cloneProducers();
+      for (Map.Entry<String, ServerProducer> entry : targetCopy.entrySet()) {
          String uuid = null;
-         if (entry.getValue().getA() != null) {
-            uuid = entry.getValue().getA().toString();
+         if (entry.getValue().getLastProducedMessageID() != null) {
+            uuid = entry.getValue().getLastProducedMessageID().toString();
          }
-         JsonObjectBuilder producerInfo = JsonLoader.createObjectBuilder().add("connectionID", this.getConnectionID().toString()).add("sessionID", this.getName()).add("destination", entry.getKey().toString()).add("lastUUIDSent", uuid, JsonValue.NULL).add("msgSent", entry.getValue().getB().longValue());
+         JsonObjectBuilder producerInfo = JsonLoader.createObjectBuilder()
+               .add(ProducerField.ID.getName(), String.valueOf(entry.getValue().getID()))
+               .add(ProducerField.NAME.getName(), entry.getValue().getName())
+               .add(ProducerField.CONNECTION_ID.getName(), this.getConnectionID().toString())
+               .add(ProducerField.SESSION.getAlternativeName(), this.getName())
+               .add(ProducerField.CREATION_TIME.getName(), String.valueOf(entry.getValue().getCreationTime()))
+               .add(ProducerField.ADDRESS.getAlternativeName(), entry.getValue().getAddress())
+               .add(ProducerField.LAST_PRODUCED_MESSAGE_ID.getName(), uuid, JsonValue.NULL)
+               .add(ProducerField.MESSAGE_SENT.getName(),  entry.getValue().getMessagesSent())
+               .add(ProducerField.MESSAGE_SENT_SIZE.getName(), entry.getValue().getMessagesSentSize());
          array.add(producerInfo);
       }
    }
@@ -2098,8 +2082,8 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
       connectionFailed(me, failedOver);
    }
 
-   public Map<SimpleString, Pair<Object, AtomicLong>> cloneTargetAddresses() {
-      return new HashMap<>(targetAddressInfos);
+   public Map<String, ServerProducer> cloneProducers() {
+      return serverProducers.cloneProducers();
    }
 
    private void setStarted(final boolean s) {
@@ -2140,7 +2124,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
          }
          reply.setAddress(replyTo);
 
-         doSend(tx, reply, null, direct, false, routingContext);
+         doSend(tx, reply, null, direct, null, false, routingContext);
       }
       return RoutingStatus.OK;
    }
@@ -2202,8 +2186,9 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
                                             final Message msg,
                                             final SimpleString originalAddress,
                                             final boolean direct,
+                                            final String senderName,
                                             final boolean noAutoCreateQueue) throws Exception {
-      return doSend(tx, msg, originalAddress, direct, noAutoCreateQueue, routingContext);
+      return doSend(tx, msg, originalAddress, direct, senderName, noAutoCreateQueue, routingContext);
    }
 
 
@@ -2212,6 +2197,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
                                             final Message msg,
                                             final SimpleString originalAddress,
                                             final boolean direct,
+                                            final String senderName,
                                             final boolean noAutoCreateQueue,
                                             final RoutingContext routingContext) throws Exception {
 
@@ -2272,14 +2258,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
 
          logger.debug("Routing result for {} = {}", msg, result);
 
-         Pair<Object, AtomicLong> value = targetAddressInfos.get(msg.getAddressSimpleString());
-
-         if (value == null) {
-            targetAddressInfos.put(msg.getAddressSimpleString(), new Pair<>(msg.getUserID(), new AtomicLong(1)));
-         } else {
-            value.setA(msg.getUserID());
-            value.getB().incrementAndGet();
-         }
+         updateProducerMetrics(msg, senderName);
       } finally {
          if (!routingContext.isReusable()) {
             routingContext.clear();
@@ -2395,20 +2374,21 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
    }
 
    @Override
-   public void addProducer(ServerProducer serverProducer) {
-      serverProducer.setSessionID(getName());
-      serverProducer.setConnectionID(getConnectionID().toString());
-      producers.put(serverProducer.getID(), serverProducer);
+   public void addProducer(String name, String protocol, String address) {
+      ServerProducer producer = new ServerProducerImpl(name, protocol, address != null ? address : ServerProducer.ANONYMOUS);
+      producer.setSessionID(getName());
+      producer.setConnectionID(getConnectionID() != null ? getConnectionID().toString() : null);
+      serverProducers.put(name, producer);
    }
 
    @Override
    public void removeProducer(String ID) {
-      producers.remove(ID);
+      serverProducers.remove(ID);
    }
 
    @Override
-   public Map<String, ServerProducer> getServerProducers() {
-      return Collections.unmodifiableMap(new HashMap(producers));
+   public Collection<ServerProducer>   getServerProducers() {
+      return serverProducers.getServerProducers();
    }
 
    @Override
@@ -2436,4 +2416,13 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
    public String toManagementString() {
       return "ServerSession [id=" + getConnectionID() + ":" + getName() + "]";
    }
+
+   private void updateProducerMetrics(Message msg, String senderName) {
+      ServerProducer serverProducer = serverProducers.getServerProducer(senderName, msg, this);
+      if (serverProducer != null) {
+         serverProducer.updateMetrics(msg.getUserID(), msg instanceof LargeServerMessageImpl ? ((LargeServerMessageImpl)msg).getBodyBufferSize() : msg.getEncodeSize());
+      }
+   }
+
+
 }
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/TransactionPropertyIndexes.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/TransactionPropertyIndexes.java
index 4ba31eeb47..d6c332a6b5 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/TransactionPropertyIndexes.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/TransactionPropertyIndexes.java
@@ -35,4 +35,6 @@ public class TransactionPropertyIndexes {
    public static final int PAGE_CURSOR_POSITIONS = 8;
 
    public static final int EXPIRY_LOGGER = 9;
+
+   public static final int CONSUMER_METRICS_OPERATION = 10;
 }
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/impl/TransactionImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/impl/TransactionImpl.java
index 27acad2130..13ee0ba73e 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/impl/TransactionImpl.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/impl/TransactionImpl.java
@@ -48,7 +48,7 @@ public class TransactionImpl implements Transaction {
 
    private List<TransactionOperation> storeOperations;
 
-   private static final int INITIAL_NUM_PROPERTIES = 10;
+   private static final int INITIAL_NUM_PROPERTIES = 11;
 
    private Object[] properties = null;
 
diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/tests/util/ActiveMQTestBase.java b/artemis-server/src/test/java/org/apache/activemq/artemis/tests/util/ActiveMQTestBase.java
index fb04c2b2a4..db80b028ab 100644
--- a/artemis-server/src/test/java/org/apache/activemq/artemis/tests/util/ActiveMQTestBase.java
+++ b/artemis-server/src/test/java/org/apache/activemq/artemis/tests/util/ActiveMQTestBase.java
@@ -65,6 +65,7 @@ import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
 import org.apache.activemq.artemis.api.core.ActiveMQException;
 import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
 import org.apache.activemq.artemis.api.core.ICoreMessage;
+import org.apache.activemq.artemis.api.core.JsonUtil;
 import org.apache.activemq.artemis.api.core.Message;
 import org.apache.activemq.artemis.api.core.Pair;
 import org.apache.activemq.artemis.api.core.QueueConfiguration;
@@ -136,6 +137,7 @@ import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
 import org.apache.activemq.artemis.core.transaction.impl.XidImpl;
 import org.apache.activemq.artemis.jdbc.store.drivers.JDBCUtils;
 import org.apache.activemq.artemis.jdbc.store.sql.SQLProvider;
+import org.apache.activemq.artemis.json.JsonObject;
 import org.apache.activemq.artemis.nativo.jlibaio.LibaioContext;
 import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
 import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
@@ -2627,6 +2629,15 @@ public abstract class ActiveMQTestBase extends Assert {
       return !hadToInterrupt;
    }
 
+   public String createJsonFilter(String fieldName, String operationName, String value) {
+      HashMap<String, Object> filterMap = new HashMap<>();
+      filterMap.put("field", fieldName);
+      filterMap.put("operation", operationName);
+      filterMap.put("value", value);
+      JsonObject jsonFilterObject = JsonUtil.toJsonObject(filterMap);
+      return jsonFilterObject.toString();
+   }
+
    protected static ReplicationEndpoint getReplicationEndpoint(ActiveMQServer server) {
       final Activation activation = server.getActivation();
       if (activation instanceof SharedNothingBackupActivation) {
diff --git a/pom.xml b/pom.xml
index ae419584e9..340bf92dca 100644
--- a/pom.xml
+++ b/pom.xml
@@ -182,7 +182,7 @@
       <activemq.version.majorVersion>1</activemq.version.majorVersion>
       <activemq.version.minorVersion>0</activemq.version.minorVersion>
       <activemq.version.microVersion>0</activemq.version.microVersion>
-      <activemq.version.incrementingVersion>133,132,131,130,129,128,127,126,125,124,123,122</activemq.version.incrementingVersion>
+      <activemq.version.incrementingVersion>134,133,132,131,130,129,128,127,126,125,124,123,122</activemq.version.incrementingVersion>
       <activemq.version.versionTag>${project.version}</activemq.version.versionTag>
       <ActiveMQ-Version>${project.version}(${activemq.version.incrementingVersion})</ActiveMQ-Version>
 
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/DummyServerConsumer.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/DummyServerConsumer.java
index 169303623a..8aebf19906 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/DummyServerConsumer.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/DummyServerConsumer.java
@@ -180,6 +180,26 @@ public class DummyServerConsumer implements ServerConsumer {
       return null;
    }
 
+   @Override
+   public void metricsAcknowledge(MessageReference ref, Transaction transaction) {
+
+   }
+
+   @Override
+   public long getMessagesInTransitSize() {
+      return 0;
+   }
+
+   @Override
+   public long getMessagesDeliveredSize() {
+      return 0;
+   }
+
+   @Override
+   public long getMessagesDelivered() {
+      return 0;
+   }
+
    @Override
    public void promptDelivery() {
 
@@ -278,4 +298,29 @@ public class DummyServerConsumer implements ServerConsumer {
       // TODO Auto-generated method stub
       return null;
    }
+
+   @Override
+   public int getMessagesInTransit() {
+      return 0;
+   }
+
+   @Override
+   public long getLastDeliveredTime() {
+      return 0;
+   }
+
+   @Override
+   public long getLastAcknowledgedTime() {
+      return 0;
+   }
+
+   @Override
+   public long getMessagesAcknowledged() {
+      return 0;
+   }
+
+   @Override
+   public int getMessagesAcknowledgedAwaitingCommit() {
+      return 0;
+   }
 }
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/HangConsumerTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/HangConsumerTest.java
index da54d4835c..8c3dfd5d93 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/HangConsumerTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/HangConsumerTest.java
@@ -595,8 +595,9 @@ public class HangConsumerTest extends ActiveMQTestBase {
                                                         OperationContext context,
                                                         boolean autoCreateQueue,
                                                         Map<SimpleString, RoutingType> prefixes,
-                                                        String securityDomain) throws Exception {
-         return new ServerSessionImpl(name, username, password, validatedUser, minLargeMessageSize, autoCommitSends, autoCommitAcks, preAcknowledge, getConfiguration().isPersistDeliveryCountBeforeDelivery(), xa, connection, getStorageManager(), getPostOffice(), getResourceManager(), getSecurityStore(), getManagementService(), this, getConfiguration().getManagementAddress(), defaultAddress == null ? null : new SimpleString(defaultAddress), new MyCallback(callback), context, getPagingManag [...]
+                                                        String securityDomain,
+                                                        boolean isLegacyProducer) throws Exception {
+         return new ServerSessionImpl(name, username, password, validatedUser, minLargeMessageSize, autoCommitSends, autoCommitAcks, preAcknowledge, getConfiguration().isPersistDeliveryCountBeforeDelivery(), xa, connection, getStorageManager(), getPostOffice(), getResourceManager(), getSecurityStore(), getManagementService(), this, getConfiguration().getManagementAddress(), defaultAddress == null ? null : new SimpleString(defaultAddress), new MyCallback(callback), context, getPagingManag [...]
       }
    }
 
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/LargeMessageTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/LargeMessageTest.java
index 5914d62b3a..774fcde742 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/LargeMessageTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/LargeMessageTest.java
@@ -29,6 +29,7 @@ import java.io.InputStream;
 import java.lang.management.ManagementFactory;
 import java.lang.management.OperatingSystemMXBean;
 import java.nio.ByteBuffer;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
@@ -61,6 +62,7 @@ import org.apache.activemq.artemis.core.server.ActiveMQServer;
 import org.apache.activemq.artemis.core.server.LargeServerMessage;
 import org.apache.activemq.artemis.core.server.MessageReference;
 import org.apache.activemq.artemis.core.server.Queue;
+import org.apache.activemq.artemis.core.server.ServerProducer;
 import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
 import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
 import org.apache.activemq.artemis.tests.integration.largemessage.LargeMessageTestBase;
@@ -2570,6 +2572,79 @@ public class LargeMessageTest extends LargeMessageTestBase {
       session.commit();
    }
 
+   @Test
+   public void testSendServerMessageMetrics() throws Exception {
+      ActiveMQServer server = createServer(true, isNetty(), storeType);
+
+      server.start();
+
+      ClientSessionFactory sf = addSessionFactory(createSessionFactory(locator));
+
+      ClientSession session = sf.createSession(false, false);
+
+      LargeServerMessageImpl fileMessage = new LargeServerMessageImpl((JournalStorageManager) server.getStorageManager());
+
+      fileMessage.setMessageID(1005);
+
+      for (int i = 0; i < largeMessageSize; i++) {
+         fileMessage.addBytes(new byte[]{ActiveMQTestBase.getSamplebyte(i)});
+      }
+
+      // The server would be doing this
+      fileMessage.putLongProperty(Message.HDR_LARGE_BODY_SIZE, largeMessageSize);
+
+      fileMessage.releaseResources(false, false);
+
+      session.createQueue(new QueueConfiguration(ADDRESS));
+
+      ClientProducer prod = session.createProducer(ADDRESS);
+
+      prod.send(fileMessage);
+
+      fileMessage.deleteFile();
+
+      session.commit();
+
+      Collection<ServerProducer> serverProducers = server.getSessions().iterator().next().getServerProducers();
+
+      Assert.assertEquals(1, serverProducers.size());
+
+      ServerProducer producer = serverProducers.iterator().next();
+
+      Assert.assertEquals(1, producer.getMessagesSent());
+
+      Assert.assertEquals(largeMessageSize, producer.getMessagesSentSize());
+
+      fileMessage = new LargeServerMessageImpl((JournalStorageManager) server.getStorageManager());
+
+      fileMessage.setMessageID(1006);
+
+      for (int i = 0; i < largeMessageSize; i++) {
+         fileMessage.addBytes(new byte[]{ActiveMQTestBase.getSamplebyte(i)});
+      }
+
+      // The server would be doing this
+      fileMessage.putLongProperty(Message.HDR_LARGE_BODY_SIZE, largeMessageSize);
+
+      fileMessage.releaseResources(false, false);
+
+      prod.send(fileMessage);
+
+      fileMessage.deleteFile();
+
+      session.commit();
+
+      serverProducers = server.getSessions().iterator().next().getServerProducers();
+
+      Assert.assertEquals(1, serverProducers.size());
+
+      producer = serverProducers.iterator().next();
+
+      Assert.assertEquals(2, producer.getMessagesSent());
+
+      Assert.assertEquals(largeMessageSize * 2, producer.getMessagesSentSize());
+   }
+
 
 
    @Override
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/client/TemporaryDestinationTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/client/TemporaryDestinationTest.java
index 91296cc895..463ad29743 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/client/TemporaryDestinationTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/client/TemporaryDestinationTest.java
@@ -279,7 +279,7 @@ public class TemporaryDestinationTest extends JMSTestBase {
          producer.send(s.createMessage());
          temporaryQueue.delete();
          for (ServerSession serverSession : server.getSessions()) {
-            assertFalse(((ServerSessionImpl)serverSession).cloneTargetAddresses().containsKey(SimpleString.toSimpleString(temporaryQueue.getQueueName())));
+            assertFalse(((ServerSessionImpl)serverSession).cloneProducers().containsKey(temporaryQueue.getQueueName()));
          }
          Wait.assertTrue(() -> server.locateQueue(temporaryQueue.getQueueName()) == null, 1000, 100);
          Wait.assertTrue(() -> server.getAddressInfo(SimpleString.toSimpleString(temporaryQueue.getQueueName())) == null, 1000, 100);
@@ -323,26 +323,6 @@ public class TemporaryDestinationTest extends JMSTestBase {
       Wait.assertTrue(() -> server.getAddressInfo(SimpleString.toSimpleString(temporaryQueue.getQueueName())) == null, 1000, 100);
    }
 
-   @Test
-   public void testForTempQueueTargetInfosSizeLimit() throws Exception {
-      try {
-         conn = createConnection();
-         Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         for (int i = 0; i < 200; i++) {
-            TemporaryQueue temporaryQueue = s.createTemporaryQueue();
-            MessageProducer producer = s.createProducer(temporaryQueue);
-            producer.send(s.createMessage());
-         }
-         for (ServerSession serverSession : server.getSessions()) {
-            assertTrue(((ServerSessionImpl)serverSession).cloneTargetAddresses().size() <= 100);
-         }
-      } finally {
-         if (conn != null) {
-            conn.close();
-         }
-      }
-   }
-
    @Test
    public void testForSecurityCacheLeak() throws Exception {
       server.getSecurityStore().setSecurityEnabled(true);
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlTest.java
index 17913f128c..cefbd969d0 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlTest.java
@@ -22,8 +22,11 @@ import javax.jms.MessageConsumer;
 import javax.jms.MessageProducer;
 import javax.jms.Session;
 import javax.jms.TextMessage;
+import javax.jms.Topic;
+import javax.jms.TopicSubscriber;
 import javax.transaction.xa.XAResource;
 import javax.transaction.xa.Xid;
+import java.lang.reflect.Field;
 import java.nio.ByteBuffer;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -34,6 +37,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
@@ -73,7 +77,10 @@ import org.apache.activemq.artemis.core.config.BridgeConfiguration;
 import org.apache.activemq.artemis.core.config.ClusterConnectionConfiguration;
 import org.apache.activemq.artemis.core.config.Configuration;
 import org.apache.activemq.artemis.core.config.impl.SecurityConfiguration;
+import org.apache.activemq.artemis.core.management.impl.view.ConsumerField;
+import org.apache.activemq.artemis.core.management.impl.view.ProducerField;
 import org.apache.activemq.artemis.core.messagecounter.impl.MessageCounterManagerImpl;
+import org.apache.activemq.artemis.core.persistence.OperationContext;
 import org.apache.activemq.artemis.core.persistence.config.PersistedDivertConfiguration;
 import org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory;
 import org.apache.activemq.artemis.core.remoting.impl.invm.TransportConstants;
@@ -84,9 +91,12 @@ import org.apache.activemq.artemis.core.server.ActiveMQServers;
 import org.apache.activemq.artemis.core.server.BrokerConnection;
 import org.apache.activemq.artemis.core.server.Queue;
 import org.apache.activemq.artemis.core.server.ServerConsumer;
+import org.apache.activemq.artemis.core.server.ServerProducer;
 import org.apache.activemq.artemis.core.server.ServerSession;
 import org.apache.activemq.artemis.core.server.ServiceComponent;
 import org.apache.activemq.artemis.core.server.impl.AddressInfo;
+import org.apache.activemq.artemis.core.server.impl.ServerLegacyProducersImpl;
+import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerSessionPlugin;
 import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
 import org.apache.activemq.artemis.core.settings.impl.DeletionPolicy;
 import org.apache.activemq.artemis.core.settings.impl.SlowConsumerPolicy;
@@ -96,8 +106,11 @@ import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
 import org.apache.activemq.artemis.jms.client.ActiveMQSession;
 import org.apache.activemq.artemis.json.JsonArray;
 import org.apache.activemq.artemis.json.JsonObject;
+import org.apache.activemq.artemis.json.JsonValue;
 import org.apache.activemq.artemis.marker.WebServerComponentMarker;
 import org.apache.activemq.artemis.nativo.jlibaio.LibaioContext;
+import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
+import org.apache.activemq.artemis.spi.core.protocol.SessionCallback;
 import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
 import org.apache.activemq.artemis.spi.core.security.jaas.InVMLoginModule;
 import org.apache.activemq.artemis.tests.unit.core.config.impl.fakes.FakeConnectorServiceFactory;
@@ -107,6 +120,7 @@ import org.apache.activemq.artemis.utils.RandomUtil;
 import org.apache.activemq.artemis.utils.RetryMethod;
 import org.apache.activemq.artemis.utils.RetryRule;
 import org.apache.activemq.artemis.utils.UUIDGenerator;
+import org.apache.qpid.jms.JmsConnectionFactory;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
@@ -128,6 +142,9 @@ public class ActiveMQServerControlTest extends ManagementTestBase {
 
    protected boolean legacyCreateQueue;
 
+   // For any extended tests that may add extra prodcuers as part of the test
+   protected int extraProducers = 0;
+
    private ActiveMQServer server;
 
    private Configuration conf;
@@ -2190,8 +2207,13 @@ public class ActiveMQServerControlTest extends ManagementTestBase {
 
       JsonArray jsonArray = JsonUtil.readJsonArray(serverControl.listProducersInfoAsJSON());
 
-      assertEquals(1, jsonArray.size());
-      assertEquals(8, ((JsonObject) jsonArray.get(0)).getInt("msgSent"));
+      assertEquals(1 + extraProducers, jsonArray.size());
+      JsonObject first = (JsonObject) jsonArray.get(0);
+      if (!first.getString(ProducerField.ADDRESS.getAlternativeName()).equalsIgnoreCase(atestq.toString())) {
+         first = (JsonObject) jsonArray.get(1);
+      }
+      assertEquals(8, ((JsonObject) first).getInt("msgSent"));
+      assertTrue(((JsonObject) first).getInt("msgSizeSent") > 0);
 
       clientSession.close();
       locator.close();
@@ -2681,29 +2703,31 @@ public class ActiveMQServerControlTest extends ManagementTestBase {
          second = array.getJsonObject(0);
       }
 
-      Assert.assertNotNull(first.getJsonNumber("consumerID").longValue());
-      Assert.assertTrue(first.getString("connectionID").length() > 0);
-      Assert.assertEquals(factory.getConnection().getID().toString(), first.getString("connectionID"));
-      Assert.assertTrue(first.getString("sessionID").length() > 0);
-      Assert.assertEquals(((ClientSessionImpl) session).getName(), first.getString("sessionID"));
-      Assert.assertTrue(first.getString("queueName").length() > 0);
-      Assert.assertEquals(queueName.toString(), first.getString("queueName"));
-      Assert.assertEquals(false, first.getBoolean("browseOnly"));
-      Assert.assertTrue(first.getJsonNumber("creationTime").longValue() > 0);
-      Assert.assertEquals(0, first.getJsonNumber("deliveringCount").longValue());
-
-      Assert.assertNotNull(second.getJsonNumber("consumerID").longValue());
-      Assert.assertTrue(second.getString("connectionID").length() > 0);
-      Assert.assertEquals(factory.getConnection().getID().toString(), second.getString("connectionID"));
-      Assert.assertTrue(second.getString("sessionID").length() > 0);
-      Assert.assertEquals(((ClientSessionImpl) session).getName(), second.getString("sessionID"));
-      Assert.assertTrue(second.getString("queueName").length() > 0);
-      Assert.assertEquals(queueName.toString(), second.getString("queueName"));
-      Assert.assertEquals(true, second.getBoolean("browseOnly"));
-      Assert.assertTrue(second.getJsonNumber("creationTime").longValue() > 0);
-      Assert.assertEquals(0, second.getJsonNumber("deliveringCount").longValue());
-      Assert.assertTrue(second.getString("filter").length() > 0);
-      Assert.assertEquals(filter, second.getString("filter"));
+      Assert.assertNotNull(first.getJsonNumber(ConsumerField.ID.getAlternativeName()).longValue());
+      Assert.assertTrue(first.getString(ConsumerField.CONNECTION.getAlternativeName()).length() > 0);
+      Assert.assertEquals(factory.getConnection().getID().toString(), first.getString(ConsumerField.CONNECTION.getAlternativeName()));
+      Assert.assertTrue(first.getString(ConsumerField.SESSION.getAlternativeName()).length() > 0);
+      Assert.assertEquals(((ClientSessionImpl) session).getName(), first.getString(ConsumerField.SESSION.getAlternativeName()));
+      Assert.assertTrue(first.getString(ConsumerField.QUEUE.getAlternativeName()).length() > 0);
+      Assert.assertEquals(queueName.toString(), first.getString(ConsumerField.QUEUE.getAlternativeName()));
+      Assert.assertEquals(false, first.getBoolean(ConsumerField.BROWSE_ONLY.getName()));
+      Assert.assertTrue(first.getJsonNumber(ConsumerField.CREATION_TIME.getName()).longValue() > 0);
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      // test the old version that has been replaced for backward compatibility
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getAlternativeName()).longValue());
+
+      Assert.assertNotNull(second.getJsonNumber(ConsumerField.ID.getAlternativeName()).longValue());
+      Assert.assertTrue(second.getString(ConsumerField.CONNECTION.getAlternativeName()).length() > 0);
+      Assert.assertEquals(factory.getConnection().getID().toString(), second.getString(ConsumerField.CONNECTION.getAlternativeName()));
+      Assert.assertTrue(second.getString(ConsumerField.SESSION.getAlternativeName()).length() > 0);
+      Assert.assertEquals(((ClientSessionImpl) session).getName(), second.getString(ConsumerField.SESSION.getAlternativeName()));
+      Assert.assertTrue(second.getString(ConsumerField.QUEUE.getAlternativeName()).length() > 0);
+      Assert.assertEquals(queueName.toString(), second.getString(ConsumerField.QUEUE.getAlternativeName()));
+      Assert.assertEquals(true, second.getBoolean(ConsumerField.BROWSE_ONLY.getName()));
+      Assert.assertTrue(second.getJsonNumber(ConsumerField.CREATION_TIME.getName()).longValue() > 0);
+      Assert.assertEquals(0, second.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertTrue(second.getString(ConsumerField.FILTER.getName()).length() > 0);
+      Assert.assertEquals(filter, second.getString(ConsumerField.FILTER.getName()));
    }
 
    @Test
@@ -2725,13 +2749,9 @@ public class ActiveMQServerControlTest extends ManagementTestBase {
          server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
 
-      Queue serverQueue = server.locateQueue(queueName);
-
       addClientConsumer(session.createConsumer(queueName));
-      Wait.assertEquals(1, serverQueue::getConsumerCount);
-      Thread.sleep(100); // we check timestamps, they need to be different
+      Thread.sleep(200);
       addClientConsumer(session2.createConsumer(queueName));
-      Wait.assertEquals(2, serverQueue::getConsumerCount);
 
       String jsonString = serverControl.listAllConsumersAsJSON();
       logger.debug(jsonString);
@@ -2739,378 +2759,964 @@ public class ActiveMQServerControlTest extends ManagementTestBase {
       JsonArray array = JsonUtil.readJsonArray(jsonString);
       Assert.assertEquals(usingCore() ? 3 : 2, array.size());
 
+      String key = "creationTime";
       JsonObject[] sorted = new JsonObject[array.size()];
       for (int i = 0; i < array.size(); i++) {
          sorted[i] = array.getJsonObject(i);
       }
 
-      JsonObject first = null;
-      JsonObject second = null;
-
-      for (JsonObject obj : sorted) {
-
-         if (obj.getString("connectionID").equals(factory.getConnection().getID().toString())) {
-            first = obj;
+      if (sorted[0].getJsonNumber(key).longValue() > sorted[1].getJsonNumber(key).longValue()) {
+         JsonObject o = sorted[1];
+         sorted[1] = sorted[0];
+         sorted[0] = o;
+      }
+      if (usingCore()) {
+         if (sorted[1].getJsonNumber(key).longValue() > sorted[2].getJsonNumber(key).longValue()) {
+            JsonObject o = sorted[2];
+            sorted[2] = sorted[1];
+            sorted[1] = o;
          }
-
-         if (obj.getString("connectionID").equals(factory2.getConnection().getID().toString())) {
-            second = obj;
+         if (sorted[0].getJsonNumber(key).longValue() > sorted[1].getJsonNumber(key).longValue()) {
+            JsonObject o = sorted[1];
+            sorted[1] = sorted[0];
+            sorted[0] = o;
          }
       }
 
-      Assert.assertNotNull(first);
-      Assert.assertNotNull(second);
-
-      Assert.assertTrue(first.getJsonNumber("creationTime").longValue() > 0);
-      Assert.assertNotNull(first.getJsonNumber("consumerID").longValue());
-      Assert.assertTrue(first.getString("connectionID").length() > 0);
-      Assert.assertEquals(factory.getConnection().getID().toString(), first.getString("connectionID"));
-      Assert.assertTrue(first.getString("sessionID").length() > 0);
-      Assert.assertEquals(((ClientSessionImpl) session).getName(), first.getString("sessionID"));
-      Assert.assertTrue(first.getString("queueName").length() > 0);
-      Assert.assertEquals(queueName.toString(), first.getString("queueName"));
-      Assert.assertEquals(false, first.getBoolean("browseOnly"));
-      Assert.assertEquals(0, first.getJsonNumber("deliveringCount").longValue());
+      JsonObject first = sorted[0];
+      JsonObject second = sorted[1];
+
+      Assert.assertTrue(first.getJsonNumber(ConsumerField.CREATION_TIME.getName()).longValue() > 0);
+      Assert.assertNotNull(first.getJsonNumber(ConsumerField.ID.getAlternativeName()).longValue());
+      Assert.assertTrue(first.getString(ConsumerField.CONNECTION.getAlternativeName()).length() > 0);
+      Assert.assertEquals(factory.getConnection().getID().toString(), first.getString(ConsumerField.CONNECTION.getAlternativeName()));
+      Assert.assertTrue(first.getString(ConsumerField.SESSION.getAlternativeName()).length() > 0);
+      Assert.assertEquals(((ClientSessionImpl) session).getName(), first.getString(ConsumerField.SESSION.getAlternativeName()));
+      Assert.assertTrue(first.getString(ConsumerField.QUEUE.getAlternativeName()).length() > 0);
+      Assert.assertEquals(queueName.toString(), first.getString(ConsumerField.QUEUE.getAlternativeName()));
+      Assert.assertEquals(false, first.getBoolean(ConsumerField.BROWSE_ONLY.getName()));
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.LAST_DELIVERED_TIME.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.LAST_ACKNOWLEDGED_TIME.getName()).longValue());
+
+      Assert.assertTrue(second.getJsonNumber(ConsumerField.CREATION_TIME.getName()).longValue() > 0);
+      Assert.assertNotNull(second.getJsonNumber(ConsumerField.ID.getAlternativeName()).longValue());
+      Assert.assertTrue(second.getString(ConsumerField.CONNECTION.getAlternativeName()).length() > 0);
+      Assert.assertEquals(factory2.getConnection().getID().toString(), second.getString(ConsumerField.CONNECTION.getAlternativeName()));
+      Assert.assertTrue(second.getString(ConsumerField.SESSION.getAlternativeName()).length() > 0);
+      Assert.assertEquals(((ClientSessionImpl) session2).getName(), second.getString(ConsumerField.SESSION.getAlternativeName()));
+      Assert.assertTrue(second.getString(ConsumerField.QUEUE.getAlternativeName()).length() > 0);
+      Assert.assertEquals(queueName.toString(), second.getString(ConsumerField.QUEUE.getAlternativeName()));
+      Assert.assertEquals(false, second.getBoolean(ConsumerField.BROWSE_ONLY.getName()));
+      Assert.assertEquals(0, second.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, second.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(0, second.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, second.getJsonNumber(ConsumerField.LAST_DELIVERED_TIME.getName()).longValue());
+      Assert.assertEquals(0, second.getJsonNumber(ConsumerField.LAST_ACKNOWLEDGED_TIME.getName()).longValue());
 
-      Assert.assertTrue(second.getJsonNumber("creationTime").longValue() > 0);
-      Assert.assertNotNull(second.getJsonNumber("consumerID").longValue());
-      Assert.assertTrue(second.getString("connectionID").length() > 0);
-      Assert.assertEquals(factory2.getConnection().getID().toString(), second.getString("connectionID"));
-      Assert.assertTrue(second.getString("sessionID").length() > 0);
-      Assert.assertEquals(((ClientSessionImpl) session2).getName(), second.getString("sessionID"));
-      Assert.assertTrue(second.getString("queueName").length() > 0);
-      Assert.assertEquals(queueName.toString(), second.getString("queueName"));
-      Assert.assertEquals(false, second.getBoolean("browseOnly"));
-      Assert.assertEquals(0, second.getJsonNumber("deliveringCount").longValue());
    }
 
+
    @Test
-   public void testListSessionsAsJSON() throws Exception {
+   public void testListAllConsumersAsJSONTXCommit() throws Exception {
       SimpleString queueName = new SimpleString(UUID.randomUUID().toString());
-      server.addAddressInfo(new AddressInfo(queueName, RoutingType.ANYCAST));
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      ServerLocator locator = createInVMNonHALocator();
+      ClientSessionFactory factory = createSessionFactory(locator);
+      ClientSession session = factory.createSession(true,false, 1);
+      addClientSession(session);
+
+      serverControl.createAddress(queueName.toString(), RoutingType.ANYCAST.name());
       if (legacyCreateQueue) {
          server.createQueue(queueName, RoutingType.ANYCAST, queueName, null, false, false);
       } else {
          server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
-      ActiveMQServerControl serverControl = createManagementControl();
 
-      ServerLocator locator = createInVMNonHALocator();
-      ClientSessionFactory factory = createSessionFactory(locator);
-      ClientSession session1 = addClientSession(factory.createSession());
-      ClientSession session2 = addClientSession(factory.createSession("myUser", "myPass", false, false, false, false, 0));
-      session2.createConsumer(queueName);
+      ClientConsumer consumer = session.createConsumer(queueName, null, 100, -1, false);
+      addClientConsumer(consumer);
+      session.start();
 
-      String jsonString = serverControl.listSessionsAsJSON(factory.getConnection().getID().toString());
+      ClientProducer producer = session.createProducer(queueName);
+      int size = 0;
+      ClientMessage receive = null;
+      for (int i = 0; i < 100; i++) {
+         ClientMessage message = session.createMessage(true);
+
+         producer.send(message);
+         size += message.getEncodeSize();
+         receive = consumer.receive();
+      }
+
+      String jsonString = serverControl.listAllConsumersAsJSON();
       logger.debug(jsonString);
       Assert.assertNotNull(jsonString);
       JsonArray array = JsonUtil.readJsonArray(jsonString);
-      Assert.assertEquals(2, array.size());
-      JsonObject first = lookupSession(array, session1);
-      JsonObject second = lookupSession(array, session2);
-
-      Assert.assertTrue(first.getString("sessionID").length() > 0);
-      Assert.assertEquals(((ClientSessionImpl) session1).getName(), first.getString("sessionID"));
-      Assert.assertTrue(first.getString("principal").length() > 0);
-      Assert.assertEquals("guest", first.getString("principal"));
-      Assert.assertTrue(first.getJsonNumber("creationTime").longValue() > 0);
-      Assert.assertEquals(0, first.getJsonNumber("consumerCount").longValue());
-
-      Assert.assertTrue(second.getString("sessionID").length() > 0);
-      Assert.assertEquals(((ClientSessionImpl) session2).getName(), second.getString("sessionID"));
-      Assert.assertTrue(second.getString("principal").length() > 0);
-      Assert.assertEquals("myUser", second.getString("principal"));
-      Assert.assertTrue(second.getJsonNumber("creationTime").longValue() > 0);
-      Assert.assertEquals(1, second.getJsonNumber("consumerCount").longValue());
-   }
-
-   private JsonObject lookupSession(JsonArray jsonArray, ClientSession session) throws Exception {
-      String name = ((ClientSessionImpl)session).getName();
-
-      for (int i = 0; i < jsonArray.size(); i++) {
-         JsonObject obj = jsonArray.getJsonObject(i);
-         String sessionID = obj.getString("sessionID");
-         Assert.assertNotNull(sessionID);
+      JsonObject first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+      receive.acknowledge();
+      session.commit();
 
-         if (sessionID.equals(name)) {
-            return obj;
-         }
+      jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      array = JsonUtil.readJsonArray(jsonString);
+      first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
       }
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+
+      int allSize = size;
+      for (int i = 0; i < 100; i++) {
+         ClientMessage message = session.createMessage(true);
 
-      Assert.fail("Sesison not found for session id " + name);
+         producer.send(message);
+         allSize += message.getEncodeSize();
+         receive = consumer.receive();
+      }
 
-      // not going to happen, fail will throw an exception but it won't compile without this
-      return null;
+      jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      array = JsonUtil.readJsonArray(jsonString);
+      first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(200, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(allSize, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
    }
 
    @Test
-   public void testListAllSessionsAsJSON() throws Exception {
+   public void testListAllConsumersAsJSONTXCommitAck() throws Exception {
       SimpleString queueName = new SimpleString(UUID.randomUUID().toString());
-      server.addAddressInfo(new AddressInfo(queueName, RoutingType.ANYCAST));
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      ServerLocator locator = createInVMNonHALocator();
+      ClientSessionFactory factory = createSessionFactory(locator);
+      ClientSession session = factory.createSession(true,false, 1);
+      addClientSession(session);
+
+      serverControl.createAddress(queueName.toString(), RoutingType.ANYCAST.name());
       if (legacyCreateQueue) {
          server.createQueue(queueName, RoutingType.ANYCAST, queueName, null, false, false);
       } else {
          server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
-      ActiveMQServerControl serverControl = createManagementControl();
 
-      ServerLocator locator = createInVMNonHALocator();
-      ClientSessionFactory factory = createSessionFactory(locator);
-      ServerLocator locator2 = createInVMNonHALocator();
-      ClientSessionFactory factory2 = createSessionFactory(locator2);
-      ClientSession session1 = addClientSession(factory.createSession());
-      Thread.sleep(5);
-      ClientSession session2 = addClientSession(factory2.createSession("myUser", "myPass", false, false, false, false, 0));
-      session2.addMetaData("foo", "bar");
-      session2.addMetaData("bar", "baz");
-      session2.createConsumer(queueName);
+      ClientConsumer consumer = session.createConsumer(queueName, null, 100, -1, false);
+      addClientConsumer(consumer);
+      session.start();
 
-      String jsonString = serverControl.listAllSessionsAsJSON();
+      ClientProducer producer = session.createProducer(queueName);
+      int size = 0;
+      ClientMessage receive = null;
+      for (int i = 0; i < 100; i++) {
+         ClientMessage message = session.createMessage(true);
+
+         producer.send(message);
+         size += message.getEncodeSize();
+         receive = consumer.receive();
+         receive.acknowledge();
+      }
+
+      Wait.assertEquals(0, () -> JsonUtil.readJsonArray(serverControl.listAllConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
+
+      String jsonString = serverControl.listAllConsumersAsJSON();
       logger.debug(jsonString);
       Assert.assertNotNull(jsonString);
       JsonArray array = JsonUtil.readJsonArray(jsonString);
-      Assert.assertEquals(2 + (usingCore() ? 1 : 0), array.size());
-      JsonObject first = lookupSession(array, session1);
-      JsonObject second = lookupSession(array, session2);
+      JsonObject first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+      session.commit();
 
-      Assert.assertTrue(first.getString("sessionID").length() > 0);
-      Assert.assertEquals(((ClientSessionImpl) session1).getName(), first.getString("sessionID"));
-      Assert.assertTrue(first.getString("principal").length() > 0);
-      Assert.assertEquals("guest", first.getString("principal"));
-      Assert.assertTrue(first.getJsonNumber("creationTime").longValue() > 0);
-      Assert.assertEquals(0, first.getJsonNumber("consumerCount").longValue());
+      Wait.assertEquals(0, () -> JsonUtil.readJsonArray(serverControl.listAllConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
 
-      Assert.assertTrue(second.getString("sessionID").length() > 0);
-      Assert.assertEquals(((ClientSessionImpl) session2).getName(), second.getString("sessionID"));
-      Assert.assertTrue(second.getString("principal").length() > 0);
-      Assert.assertEquals("myUser", second.getString("principal"));
-      Assert.assertTrue(second.getJsonNumber("creationTime").longValue() > 0);
-      Assert.assertEquals(1, second.getJsonNumber("consumerCount").longValue());
-      Assert.assertEquals(second.getJsonObject("metadata").getJsonString("foo").getString(), "bar");
-      Assert.assertEquals(second.getJsonObject("metadata").getJsonString("bar").getString(), "baz");
+      jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      array = JsonUtil.readJsonArray(jsonString);
+      first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
    }
 
    @Test
-   public void testListAllSessionsAsJSONWithJMS() throws Exception {
+   public void testListAllConsumersAsJSONTXRollback() throws Exception {
       SimpleString queueName = new SimpleString(UUID.randomUUID().toString());
-      server.addAddressInfo(new AddressInfo(queueName, RoutingType.ANYCAST));
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      ServerLocator locator = createInVMNonHALocator();
+      ClientSessionFactory factory = createSessionFactory(locator);
+      ClientSession session = factory.createSession(true,false, 1);
+      addClientSession(session);
+
+      serverControl.createAddress(queueName.toString(), RoutingType.ANYCAST.name());
       if (legacyCreateQueue) {
          server.createQueue(queueName, RoutingType.ANYCAST, queueName, null, false, false);
       } else {
          server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
-      ActiveMQServerControl serverControl = createManagementControl();
 
-      ActiveMQConnectionFactory cf = ActiveMQJMSClient.createConnectionFactory("vm://0", "cf");
-      Connection con = cf.createConnection();
-      String clientID = UUID.randomUUID().toString();
-      con.setClientID(clientID);
+      ClientConsumer consumer = session.createConsumer(queueName, null, 100, -1, false);
+      addClientConsumer(consumer);
+      session.start();
 
-      String jsonString = serverControl.listAllSessionsAsJSON();
+      ClientProducer producer = session.createProducer(queueName);
+      int size = 0;
+      ClientMessage receive = null;
+      for (int i = 0; i < 100; i++) {
+         ClientMessage message = session.createMessage(true);
+
+         producer.send(message);
+         size += message.getEncodeSize();
+         receive = consumer.receive();
+      }
+
+      String jsonString = serverControl.listAllConsumersAsJSON();
       logger.debug(jsonString);
       Assert.assertNotNull(jsonString);
       JsonArray array = JsonUtil.readJsonArray(jsonString);
-      Assert.assertEquals(1 + (usingCore() ? 1 : 0), array.size());
-      JsonObject obj = lookupSession(array, ((ActiveMQConnection)con).getInitialSession());
-      Assert.assertEquals(obj.getJsonObject("metadata").getJsonString(ClientSession.JMS_SESSION_CLIENT_ID_PROPERTY).getString(), clientID);
-      Assert.assertNotNull(obj.getJsonObject("metadata").getJsonString(ClientSession.JMS_SESSION_IDENTIFIER_PROPERTY));
+      JsonObject first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+      receive.acknowledge();   //stop the session so we dont receive the same messages
+      session.stop();
+      jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      array = JsonUtil.readJsonArray(jsonString);
+      first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+
+      session.rollback();
+      jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      array = JsonUtil.readJsonArray(jsonString);
+      first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+
+      int allSize = size * 2;
+      session.start();
+      for (int i = 0; i < 100; i++) {
+         receive = consumer.receive();
+      }
+
+      jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      array = JsonUtil.readJsonArray(jsonString);
+      first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(200, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(allSize, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+
+      receive.acknowledge();
+      //stop the session so we dont receive the same messages
+      session.stop();
+      session.rollback();
+      jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      array = JsonUtil.readJsonArray(jsonString);
+      first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(200, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(allSize, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(200, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
    }
 
    @Test
-   public void testListQueues() throws Exception {
-      SimpleString queueName1 = new SimpleString("my_queue_one");
-      SimpleString queueName2 = new SimpleString("my_queue_two");
-      SimpleString queueName3 = new SimpleString("other_queue_three");
-
+   public void testListAllConsumersAsJSONCancel() throws Exception {
+      SimpleString queueName = new SimpleString(UUID.randomUUID().toString());
       ActiveMQServerControl serverControl = createManagementControl();
 
-      server.addAddressInfo(new AddressInfo(queueName1, RoutingType.ANYCAST));
+      ServerLocator locator = createInVMNonHALocator();
+      ClientSessionFactory factory = createSessionFactory(locator);
+      ClientSession session = factory.createSession(true,false, 1);
+      addClientSession(session);
+
+      serverControl.createAddress(queueName.toString(), RoutingType.ANYCAST.name());
       if (legacyCreateQueue) {
-         server.createQueue(queueName1, RoutingType.ANYCAST, queueName1, null, false, false);
+         server.createQueue(queueName, RoutingType.ANYCAST, queueName, null, false, false);
       } else {
-         server.createQueue(new QueueConfiguration(queueName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+         server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
 
-      server.addAddressInfo(new AddressInfo(queueName2, RoutingType.ANYCAST));
-      if (legacyCreateQueue) {
-         server.createQueue(queueName2, RoutingType.ANYCAST, queueName2, null, false, false);
-      } else {
-         server.createQueue(new QueueConfiguration(queueName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      ClientConsumer consumer = session.createConsumer(queueName, null, 100, -1, false);
+      addClientConsumer(consumer);
+      session.start();
+
+      ClientProducer producer = session.createProducer(queueName);
+      int size = 0;
+      ClientMessage receive = null;
+      for (int i = 0; i < 100; i++) {
+         ClientMessage message = session.createMessage(true);
+
+         producer.send(message);
+         size += message.getEncodeSize();
+         receive = consumer.receive();
       }
 
-      server.addAddressInfo(new AddressInfo(queueName3, RoutingType.ANYCAST));
-      if (legacyCreateQueue) {
-         server.createQueue(queueName3, RoutingType.ANYCAST, queueName3, null, false, false);
-      } else {
-         server.createQueue(new QueueConfiguration(queueName3).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      String jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      JsonArray array = JsonUtil.readJsonArray(jsonString);
+      JsonObject first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
       }
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+      receive.acknowledge();
+      //close the consumer to cancel messages and recreate
+      consumer.close();
+      session.close();
+      session = factory.createSession(true,false, 1);
+      addClientSession(session);
 
-      //test with filter that matches 2 queues
-      String filterString = createJsonFilter("name", "CONTAINS", "my_queue");
+      consumer = session.createConsumer(queueName, null, 100, -1, false);
+      addClientConsumer(consumer);
+      jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      array = JsonUtil.readJsonArray(jsonString);
+      first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+   }
 
-      String queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+   @Test
+   public void testListAllConsumersAsJSONNoTX() throws Exception {
+      SimpleString queueName = new SimpleString(UUID.randomUUID().toString());
+      ActiveMQServerControl serverControl = createManagementControl();
 
-      JsonObject queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-      JsonArray array = (JsonArray) queuesAsJsonObject.get("data");
+      ServerLocator locator = createInVMNonHALocator();
+      ClientSessionFactory factory = createSessionFactory(locator);
+      ClientSession session = factory.createSession(true, true, 1);
+      addClientSession(session);
 
-      Assert.assertEquals("number of queues returned from query", 2, array.size());
-      Assert.assertTrue(array.getJsonObject(0).getString("name").contains("my_queue"));
-      Assert.assertTrue(array.getJsonObject(1).getString("name").contains("my_queue"));
+      serverControl.createAddress(queueName.toString(), RoutingType.ANYCAST.name());
+      if (legacyCreateQueue) {
+         server.createQueue(queueName, RoutingType.ANYCAST, queueName, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
 
-      //test with an empty filter
-      filterString = createJsonFilter("", "", "");
+      ClientConsumer consumer = session.createConsumer(queueName, null, 100, -1, false);
+      addClientConsumer(consumer);
+      session.start();
 
-      queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+      ClientProducer producer = session.createProducer(queueName);
+      int size = 0;
+      ClientMessage receive = null;
+      for (int i = 0; i < 100; i++) {
+         ClientMessage message = session.createMessage(true);
 
-      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-      array = (JsonArray) queuesAsJsonObject.get("data");
+         producer.send(message);
+         size += message.getEncodeSize();
+         receive = consumer.receive();
+         receive.acknowledge();
+      }
 
-      // at least 3 queues or more
-      Assert.assertTrue("number of queues returned from query", 3 <= array.size());
+      Wait.assertEquals(0, () -> JsonUtil.readJsonArray(serverControl.listAllConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
 
-      //test with small page size
-      queuesAsJsonString = serverControl.listQueues(filterString, 1, 1);
-
-      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-      array = (JsonArray) queuesAsJsonObject.get("data");
-
-      Assert.assertEquals("number of queues returned from query", 1, array.size());
-      //check all field names are available
-      Assert.assertNotEquals("name", "", array.getJsonObject(0).getString("name"));
-      Assert.assertNotEquals("id", "", array.getJsonObject(0).getString("id"));
-      Assert.assertNotEquals("address", "", array.getJsonObject(0).getString("address"));
-      Assert.assertEquals("filter", "", array.getJsonObject(0).getString("filter"));
-      Assert.assertEquals("durable", "false", array.getJsonObject(0).getString("durable"));
-      Assert.assertEquals("paused", "false", array.getJsonObject(0).getString("paused"));
-      Assert.assertNotEquals("temporary", "", array.getJsonObject(0).getString("temporary"));
-      Assert.assertEquals("purgeOnNoConsumers", "false", array.getJsonObject(0).getString("purgeOnNoConsumers"));
-      Assert.assertNotEquals("consumerCount", "", array.getJsonObject(0).getString("consumerCount"));
-      Assert.assertEquals("maxConsumers", "-1", array.getJsonObject(0).getString("maxConsumers"));
-      Assert.assertEquals("autoCreated", "false", array.getJsonObject(0).getString("autoCreated"));
-      Assert.assertEquals("user", usingCore() ? "guest" : "", array.getJsonObject(0).getString("user"));
-      Assert.assertNotEquals("routingType", "", array.getJsonObject(0).getString("routingType"));
-      Assert.assertEquals("messagesAdded", "0", array.getJsonObject(0).getString("messagesAdded"));
-      Assert.assertEquals("messageCount", "0", array.getJsonObject(0).getString("messageCount"));
-      Assert.assertEquals("messagesAcked", "0", array.getJsonObject(0).getString("messagesAcked"));
-      Assert.assertEquals("deliveringCount", "0", array.getJsonObject(0).getString("deliveringCount"));
-      Assert.assertEquals("messagesKilled", "0", array.getJsonObject(0).getString("messagesKilled"));
-      Assert.assertEquals("exclusive", "false", array.getJsonObject(0).getString("exclusive"));
-      Assert.assertEquals("lastValue", "false", array.getJsonObject(0).getString("lastValue"));
-      Assert.assertEquals("scheduledCount", "0", array.getJsonObject(0).getString("scheduledCount"));
-      Assert.assertEquals("groupRebalance", "false", array.getJsonObject(0).getString("groupRebalance"));
-      Assert.assertEquals("groupBuckets", "-1", array.getJsonObject(0).getString("groupBuckets"));
-      Assert.assertEquals("groupFirstKey", "", array.getJsonObject(0).getString("groupFirstKey"));
-      Assert.assertEquals("autoDelete", "false", array.getJsonObject(0).getString("autoDelete"));
+      String jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      JsonArray array = JsonUtil.readJsonArray(jsonString);
+      JsonObject first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
    }
 
    @Test
-   public void testListQueuesOrder() throws Exception {
-      SimpleString queueName1 = new SimpleString("my_queue_1");
-      SimpleString queueName2 = new SimpleString("my_queue_2");
-      SimpleString queueName3 = new SimpleString("my_queue_3");
-
+   public void testListAllConsumersAsJSONXACommit() throws Exception {
+      SimpleString queueName = new SimpleString(UUID.randomUUID().toString());
       ActiveMQServerControl serverControl = createManagementControl();
 
-      server.addAddressInfo(new AddressInfo(queueName1, RoutingType.ANYCAST));
+      ServerLocator locator = createInVMNonHALocator();
+      ClientSessionFactory factory = createSessionFactory(locator);
+      ClientSession sendSession = factory.createSession();
+      addClientSession(sendSession);
+      ClientSession session = factory.createSession(true, false, false);
+      addClientSession(session);
+
+      serverControl.createAddress(queueName.toString(), RoutingType.ANYCAST.name());
       if (legacyCreateQueue) {
-         server.createQueue(queueName1, RoutingType.ANYCAST, queueName1, new SimpleString("filter1"),null,true,
-                            false, false,20,false,false);
+         server.createQueue(queueName, RoutingType.ANYCAST, queueName, null, false, false);
       } else {
-         server.createQueue(new QueueConfiguration(queueName1).setRoutingType(RoutingType.ANYCAST).setFilterString("filter1").setMaxConsumers(20).setAutoCreateAddress(false));
+         server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
-      Thread.sleep(500);
-      server.addAddressInfo(new AddressInfo(queueName2, RoutingType.ANYCAST));
+
+      ClientConsumer consumer = session.createConsumer(queueName, null, 100, -1, false);
+      addClientConsumer(consumer);
+      session.start();
+      Xid xid = new XidImpl("xa1".getBytes(), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());
+      session.start(xid, XAResource.TMNOFLAGS);
+
+      ClientProducer producer = sendSession.createProducer(queueName);
+      int size = 0;
+      ClientMessage receive = null;
+      for (int i = 0; i < 100; i++) {
+         ClientMessage message = sendSession.createMessage(true);
+
+         producer.send(message);
+         size += message.getEncodeSize();
+         receive = consumer.receive();
+         receive.acknowledge();
+      }
+
+      String jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      JsonArray array = JsonUtil.readJsonArray(jsonString);
+      JsonObject first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+
+      session.end(xid, XAResource.TMSUCCESS);
+      session.prepare(xid);
+      jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      array = JsonUtil.readJsonArray(jsonString);
+      first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+      session.commit(xid, false);
+      jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      array = JsonUtil.readJsonArray(jsonString);
+      first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+   }
+
+   @Test
+   public void testListAllConsumersAsJSONXARollback() throws Exception {
+      SimpleString queueName = new SimpleString(UUID.randomUUID().toString());
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      ServerLocator locator = createInVMNonHALocator();
+      ClientSessionFactory factory = createSessionFactory(locator);
+      ClientSession sendSession = factory.createSession();
+      addClientSession(sendSession);
+      ClientSession session = factory.createSession(true, false, false);
+      addClientSession(session);
+
+      serverControl.createAddress(queueName.toString(), RoutingType.ANYCAST.name());
       if (legacyCreateQueue) {
-         server.createQueue(queueName2, RoutingType.ANYCAST, queueName2, new SimpleString("filter3"), null,true,
-                            false, true,40,false,false);
+         server.createQueue(queueName, RoutingType.ANYCAST, queueName, null, false, false);
       } else {
-         server.createQueue(new QueueConfiguration(queueName2).setRoutingType(RoutingType.ANYCAST).setFilterString("filter3").setAutoCreated(true).setMaxConsumers(40).setAutoCreateAddress(false));
+         server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
-      Thread.sleep(500);
-      server.addAddressInfo(new AddressInfo(queueName3, RoutingType.ANYCAST));
+
+      ClientConsumer consumer = session.createConsumer(queueName, null, 100, -1, false);
+      addClientConsumer(consumer);
+      session.start();
+      Xid xid = new XidImpl("xa1".getBytes(), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());
+      session.start(xid, XAResource.TMNOFLAGS);
+
+      ClientProducer producer = sendSession.createProducer(queueName);
+      int size = 0;
+      ClientMessage receive = null;
+      for (int i = 0; i < 100; i++) {
+         ClientMessage message = sendSession.createMessage(true);
+
+         producer.send(message);
+         size += message.getEncodeSize();
+         receive = consumer.receive();
+         receive.acknowledge();
+      }
+
+      String jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      JsonArray array = JsonUtil.readJsonArray(jsonString);
+      JsonObject first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+
+      session.end(xid, XAResource.TMSUCCESS);
+      session.prepare(xid);
+      jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      array = JsonUtil.readJsonArray(jsonString);
+      first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+      session.stop();
+      session.rollback(xid);
+      jsonString = serverControl.listAllConsumersAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      array = JsonUtil.readJsonArray(jsonString);
+      first = (JsonObject) array.get(0);
+      if (!first.getString(ConsumerField.QUEUE.getAlternativeName()).equalsIgnoreCase(queueName.toString())) {
+         first = (JsonObject) array.get(1);
+      }
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED.getName()).longValue());
+      Assert.assertEquals(size, first.getJsonNumber(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()).longValue());
+      Assert.assertEquals(100, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()).longValue());
+      Assert.assertEquals(0, first.getJsonNumber(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()).longValue());
+   }
+
+   @Test
+   public void testListSessionsAsJSON() throws Exception {
+      SimpleString queueName = new SimpleString(UUID.randomUUID().toString());
+      server.addAddressInfo(new AddressInfo(queueName, RoutingType.ANYCAST));
       if (legacyCreateQueue) {
-         server.createQueue(queueName3, RoutingType.ANYCAST, queueName3,  new SimpleString("filter0"),null,true,
-                            false, false,10,false,false);
+         server.createQueue(queueName, RoutingType.ANYCAST, queueName, null, false, false);
       } else {
-         server.createQueue(new QueueConfiguration(queueName3).setRoutingType(RoutingType.ANYCAST).setFilterString("filter0").setMaxConsumers(10).setAutoCreateAddress(false));
+         server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
+      ActiveMQServerControl serverControl = createManagementControl();
 
-      //test default order
-      String filterString = createJsonFilter("name", "CONTAINS", "my_queue");
-      String queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
-      JsonObject queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-      JsonArray array = (JsonArray) queuesAsJsonObject.get("data");
+      ServerLocator locator = createInVMNonHALocator();
+      ClientSessionFactory factory = createSessionFactory(locator);
+      ClientSession session1 = addClientSession(factory.createSession());
+      ClientSession session2 = addClientSession(factory.createSession("myUser", "myPass", false, false, false, false, 0));
+      session2.createConsumer(queueName);
 
-      Assert.assertEquals("number of queues returned from query", 3, array.size());
-      Assert.assertEquals("queue1 default Order", queueName1.toString(), array.getJsonObject(0).getString("name"));
-      Assert.assertEquals("queue2 default Order", queueName2.toString(), array.getJsonObject(1).getString("name"));
-      Assert.assertEquals("queue3 default Order", queueName3.toString(), array.getJsonObject(2).getString("name"));
+      String jsonString = serverControl.listSessionsAsJSON(factory.getConnection().getID().toString());
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      JsonArray array = JsonUtil.readJsonArray(jsonString);
+      Assert.assertEquals(2, array.size());
+      JsonObject first = lookupSession(array, session1);
+      JsonObject second = lookupSession(array, session2);
 
-      //test ordered by id desc
-      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "id", "desc");
-      queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
-      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-      array = (JsonArray) queuesAsJsonObject.get("data");
+      Assert.assertTrue(first.getString("sessionID").length() > 0);
+      Assert.assertEquals(((ClientSessionImpl) session1).getName(), first.getString("sessionID"));
+      Assert.assertTrue(first.getString("principal").length() > 0);
+      Assert.assertEquals("guest", first.getString("principal"));
+      Assert.assertTrue(first.getJsonNumber("creationTime").longValue() > 0);
+      Assert.assertEquals(0, first.getJsonNumber("consumerCount").longValue());
 
-      Assert.assertEquals("number of queues returned from query", 3, array.size());
-      Assert.assertEquals("queue3 ordered by id", queueName3.toString(), array.getJsonObject(0).getString("name"));
-      Assert.assertEquals("queue2 ordered by id", queueName2.toString(), array.getJsonObject(1).getString("name"));
-      Assert.assertEquals("queue1 ordered by id", queueName1.toString(), array.getJsonObject(2).getString("name"));
+      Assert.assertTrue(second.getString("sessionID").length() > 0);
+      Assert.assertEquals(((ClientSessionImpl) session2).getName(), second.getString("sessionID"));
+      Assert.assertTrue(second.getString("principal").length() > 0);
+      Assert.assertEquals("myUser", second.getString("principal"));
+      Assert.assertTrue(second.getJsonNumber("creationTime").longValue() > 0);
+      Assert.assertEquals(1, second.getJsonNumber("consumerCount").longValue());
+   }
 
-      //ordered by address desc
-      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "address", "desc");
-      queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
-      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-      array = (JsonArray) queuesAsJsonObject.get("data");
+   private JsonObject lookupSession(JsonArray jsonArray, ClientSession session) throws Exception {
+      String name = ((ClientSessionImpl)session).getName();
 
-      Assert.assertEquals("number of queues returned from query", 3, array.size());
-      Assert.assertEquals("queue3 ordered by address", queueName3.toString(), array.getJsonObject(0).getString("name"));
-      Assert.assertEquals("queue2 ordered by address", queueName2.toString(), array.getJsonObject(1).getString("name"));
-      Assert.assertEquals("queue1 ordered by address", queueName1.toString(), array.getJsonObject(2).getString("name"));
+      for (int i = 0; i < jsonArray.size(); i++) {
+         JsonObject obj = jsonArray.getJsonObject(i);
+         String sessionID = obj.getString("sessionID");
+         Assert.assertNotNull(sessionID);
 
-      //ordered by auto create desc
-      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "autoCreated", "asc");
-      queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
-      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-      array = (JsonArray) queuesAsJsonObject.get("data");
+         if (sessionID.equals(name)) {
+            return obj;
+         }
+      }
 
-      Assert.assertEquals("number of queues returned from query", 3, array.size());
-      Assert.assertEquals("pos1 ordered by autocreate", "false", array.getJsonObject(0).getString("autoCreated"));
-      Assert.assertEquals("pos2 ordered by autocreate", "false", array.getJsonObject(1).getString("autoCreated"));
-      Assert.assertEquals("pos3 ordered by autocreate", "true", array.getJsonObject(2).getString("autoCreated"));
+      Assert.fail("Sesison not found for session id " + name);
 
-      //ordered by filter desc
-      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "filter", "desc");
-      queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
-      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-      array = (JsonArray) queuesAsJsonObject.get("data");
+      // not going to happen, fail will throw an exception but it won't compile without this
+      return null;
+   }
 
-      Assert.assertEquals("number of queues returned from query", 3, array.size());
-      Assert.assertEquals("queue2 ordered by filter", queueName2.toString(), array.getJsonObject(0).getString("name"));
-      Assert.assertEquals("queue1 ordered by filter", queueName1.toString(), array.getJsonObject(1).getString("name"));
-      Assert.assertEquals("queue3 ordered by filter", queueName3.toString(), array.getJsonObject(2).getString("name"));
+   @Test
+   public void testListAllSessionsAsJSON() throws Exception {
+      SimpleString queueName = new SimpleString(UUID.randomUUID().toString());
+      server.addAddressInfo(new AddressInfo(queueName, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName, RoutingType.ANYCAST, queueName, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+      ActiveMQServerControl serverControl = createManagementControl();
 
-      //ordered by max consumers asc
-      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "maxConsumers", "asc");
-      queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
-      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-      array = (JsonArray) queuesAsJsonObject.get("data");
+      ServerLocator locator = createInVMNonHALocator();
+      ClientSessionFactory factory = createSessionFactory(locator);
+      ServerLocator locator2 = createInVMNonHALocator();
+      ClientSessionFactory factory2 = createSessionFactory(locator2);
+      ClientSession session1 = addClientSession(factory.createSession());
+      Thread.sleep(5);
+      ClientSession session2 = addClientSession(factory2.createSession("myUser", "myPass", false, false, false, false, 0));
+      session2.addMetaData("foo", "bar");
+      session2.addMetaData("bar", "baz");
+      session2.createConsumer(queueName);
 
-      Assert.assertEquals("number of queues returned from query", 3, array.size());
-      Assert.assertEquals("queue3 ordered by filter", queueName3.toString(), array.getJsonObject(0).getString("name"));
-      Assert.assertEquals("queue1 ordered by filter", queueName1.toString(), array.getJsonObject(1).getString("name"));
-      Assert.assertEquals("queue2 ordered by filter", queueName2.toString(), array.getJsonObject(2).getString("name"));
+      String jsonString = serverControl.listAllSessionsAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      JsonArray array = JsonUtil.readJsonArray(jsonString);
+      Assert.assertEquals(2 + (usingCore() ? 1 : 0), array.size());
+      JsonObject first = lookupSession(array, session1);
+      JsonObject second = lookupSession(array, session2);
 
-      //ordering between the pages
-      //page 1
-      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "address", "desc");
-      queuesAsJsonString = serverControl.listQueues(filterString, 1, 1);
-      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-      array = (JsonArray) queuesAsJsonObject.get("data");
-      Assert.assertEquals("number of queues returned from query", 1, array.size());
-      Assert.assertEquals("queue3 ordered by page", queueName3.toString(), array.getJsonObject(0).getString("name"));
+      Assert.assertTrue(first.getString("sessionID").length() > 0);
+      Assert.assertEquals(((ClientSessionImpl) session1).getName(), first.getString("sessionID"));
+      Assert.assertTrue(first.getString("principal").length() > 0);
+      Assert.assertEquals("guest", first.getString("principal"));
+      Assert.assertTrue(first.getJsonNumber("creationTime").longValue() > 0);
+      Assert.assertEquals(0, first.getJsonNumber("consumerCount").longValue());
 
-      //page 2
+      Assert.assertTrue(second.getString("sessionID").length() > 0);
+      Assert.assertEquals(((ClientSessionImpl) session2).getName(), second.getString("sessionID"));
+      Assert.assertTrue(second.getString("principal").length() > 0);
+      Assert.assertEquals("myUser", second.getString("principal"));
+      Assert.assertTrue(second.getJsonNumber("creationTime").longValue() > 0);
+      Assert.assertEquals(1, second.getJsonNumber("consumerCount").longValue());
+      Assert.assertEquals(second.getJsonObject("metadata").getJsonString("foo").getString(), "bar");
+      Assert.assertEquals(second.getJsonObject("metadata").getJsonString("bar").getString(), "baz");
+   }
+
+   @Test
+   public void testListAllSessionsAsJSONWithJMS() throws Exception {
+      SimpleString queueName = new SimpleString(UUID.randomUUID().toString());
+      server.addAddressInfo(new AddressInfo(queueName, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName, RoutingType.ANYCAST, queueName, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      ActiveMQConnectionFactory cf = ActiveMQJMSClient.createConnectionFactory("vm://0", "cf");
+      Connection con = cf.createConnection();
+      String clientID = UUID.randomUUID().toString();
+      con.setClientID(clientID);
+
+      String jsonString = serverControl.listAllSessionsAsJSON();
+      logger.debug(jsonString);
+      Assert.assertNotNull(jsonString);
+      JsonArray array = JsonUtil.readJsonArray(jsonString);
+      Assert.assertEquals(1 + (usingCore() ? 1 : 0), array.size());
+      JsonObject obj = lookupSession(array, ((ActiveMQConnection)con).getInitialSession());
+      Assert.assertEquals(obj.getJsonObject("metadata").getJsonString(ClientSession.JMS_SESSION_CLIENT_ID_PROPERTY).getString(), clientID);
+      Assert.assertNotNull(obj.getJsonObject("metadata").getJsonString(ClientSession.JMS_SESSION_IDENTIFIER_PROPERTY));
+   }
+
+   @Test
+   public void testListQueues() throws Exception {
+      SimpleString queueName1 = new SimpleString("my_queue_one");
+      SimpleString queueName2 = new SimpleString("my_queue_two");
+      SimpleString queueName3 = new SimpleString("other_queue_three");
+
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(queueName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName1, RoutingType.ANYCAST, queueName1, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      server.addAddressInfo(new AddressInfo(queueName2, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName2, RoutingType.ANYCAST, queueName2, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      server.addAddressInfo(new AddressInfo(queueName3, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName3, RoutingType.ANYCAST, queueName3, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName3).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      //test with filter that matches 2 queues
+      String filterString = createJsonFilter("name", "CONTAINS", "my_queue");
+
+      String queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+      JsonObject queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+      JsonArray array = (JsonArray) queuesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of queues returned from query", 2, array.size());
+      Assert.assertTrue(array.getJsonObject(0).getString("name").contains("my_queue"));
+      Assert.assertTrue(array.getJsonObject(1).getString("name").contains("my_queue"));
+
+      //test with an empty filter
+      filterString = createJsonFilter("", "", "");
+
+      queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+      array = (JsonArray) queuesAsJsonObject.get("data");
+
+      // at least 3 queues or more
+      Assert.assertTrue("number of queues returned from query", 3 <= array.size());
+
+      //test with small page size
+      queuesAsJsonString = serverControl.listQueues(filterString, 1, 1);
+
+      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+      array = (JsonArray) queuesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of queues returned from query", 1, array.size());
+      //check all field names are available
+      Assert.assertNotEquals("name", "", array.getJsonObject(0).getString("name"));
+      Assert.assertNotEquals("id", "", array.getJsonObject(0).getString("id"));
+      Assert.assertNotEquals("address", "", array.getJsonObject(0).getString("address"));
+      Assert.assertEquals("filter", "", array.getJsonObject(0).getString("filter"));
+      Assert.assertEquals("durable", "false", array.getJsonObject(0).getString("durable"));
+      Assert.assertEquals("paused", "false", array.getJsonObject(0).getString("paused"));
+      Assert.assertNotEquals("temporary", "", array.getJsonObject(0).getString("temporary"));
+      Assert.assertEquals("purgeOnNoConsumers", "false", array.getJsonObject(0).getString("purgeOnNoConsumers"));
+      Assert.assertNotEquals("consumerCount", "", array.getJsonObject(0).getString("consumerCount"));
+      Assert.assertEquals("maxConsumers", "-1", array.getJsonObject(0).getString("maxConsumers"));
+      Assert.assertEquals("autoCreated", "false", array.getJsonObject(0).getString("autoCreated"));
+      Assert.assertEquals("user", usingCore() ? "guest" : "", array.getJsonObject(0).getString("user"));
+      Assert.assertNotEquals("routingType", "", array.getJsonObject(0).getString("routingType"));
+      Assert.assertEquals("messagesAdded", "0", array.getJsonObject(0).getString("messagesAdded"));
+      Assert.assertEquals("messageCount", "0", array.getJsonObject(0).getString("messageCount"));
+      Assert.assertEquals("messagesAcked", "0", array.getJsonObject(0).getString("messagesAcked"));
+      Assert.assertEquals("deliveringCount", "0", array.getJsonObject(0).getString("deliveringCount"));
+      Assert.assertEquals("messagesKilled", "0", array.getJsonObject(0).getString("messagesKilled"));
+      Assert.assertEquals("exclusive", "false", array.getJsonObject(0).getString("exclusive"));
+      Assert.assertEquals("lastValue", "false", array.getJsonObject(0).getString("lastValue"));
+      Assert.assertEquals("scheduledCount", "0", array.getJsonObject(0).getString("scheduledCount"));
+      Assert.assertEquals("groupRebalance", "false", array.getJsonObject(0).getString("groupRebalance"));
+      Assert.assertEquals("groupBuckets", "-1", array.getJsonObject(0).getString("groupBuckets"));
+      Assert.assertEquals("groupFirstKey", "", array.getJsonObject(0).getString("groupFirstKey"));
+      Assert.assertEquals("autoDelete", "false", array.getJsonObject(0).getString("autoDelete"));
+   }
+
+   @Test
+   public void testListQueuesOrder() throws Exception {
+      SimpleString queueName1 = new SimpleString("my_queue_1");
+      SimpleString queueName2 = new SimpleString("my_queue_2");
+      SimpleString queueName3 = new SimpleString("my_queue_3");
+
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(queueName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName1, RoutingType.ANYCAST, queueName1, new SimpleString("filter1"),null,true,
+                            false, false,20,false,false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setRoutingType(RoutingType.ANYCAST).setFilterString("filter1").setMaxConsumers(20).setAutoCreateAddress(false));
+      }
+      Thread.sleep(500);
+      server.addAddressInfo(new AddressInfo(queueName2, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName2, RoutingType.ANYCAST, queueName2, new SimpleString("filter3"), null,true,
+                            false, true,40,false,false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName2).setRoutingType(RoutingType.ANYCAST).setFilterString("filter3").setAutoCreated(true).setMaxConsumers(40).setAutoCreateAddress(false));
+      }
+      Thread.sleep(500);
+      server.addAddressInfo(new AddressInfo(queueName3, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName3, RoutingType.ANYCAST, queueName3,  new SimpleString("filter0"),null,true,
+                            false, false,10,false,false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName3).setRoutingType(RoutingType.ANYCAST).setFilterString("filter0").setMaxConsumers(10).setAutoCreateAddress(false));
+      }
+
+      //test default order
+      String filterString = createJsonFilter("name", "CONTAINS", "my_queue");
+      String queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+      JsonObject queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+      JsonArray array = (JsonArray) queuesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of queues returned from query", 3, array.size());
+      Assert.assertEquals("queue1 default Order", queueName1.toString(), array.getJsonObject(0).getString("name"));
+      Assert.assertEquals("queue2 default Order", queueName2.toString(), array.getJsonObject(1).getString("name"));
+      Assert.assertEquals("queue3 default Order", queueName3.toString(), array.getJsonObject(2).getString("name"));
+
+      //test ordered by id desc
+      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "id", "desc");
+      queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+      array = (JsonArray) queuesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of queues returned from query", 3, array.size());
+      Assert.assertEquals("queue3 ordered by id", queueName3.toString(), array.getJsonObject(0).getString("name"));
+      Assert.assertEquals("queue2 ordered by id", queueName2.toString(), array.getJsonObject(1).getString("name"));
+      Assert.assertEquals("queue1 ordered by id", queueName1.toString(), array.getJsonObject(2).getString("name"));
+
+      //ordered by address desc
+      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "address", "desc");
+      queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+      array = (JsonArray) queuesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of queues returned from query", 3, array.size());
+      Assert.assertEquals("queue3 ordered by address", queueName3.toString(), array.getJsonObject(0).getString("name"));
+      Assert.assertEquals("queue2 ordered by address", queueName2.toString(), array.getJsonObject(1).getString("name"));
+      Assert.assertEquals("queue1 ordered by address", queueName1.toString(), array.getJsonObject(2).getString("name"));
+
+      //ordered by auto create desc
+      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "autoCreated", "asc");
+      queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+      array = (JsonArray) queuesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of queues returned from query", 3, array.size());
+      Assert.assertEquals("pos1 ordered by autocreate", "false", array.getJsonObject(0).getString("autoCreated"));
+      Assert.assertEquals("pos2 ordered by autocreate", "false", array.getJsonObject(1).getString("autoCreated"));
+      Assert.assertEquals("pos3 ordered by autocreate", "true", array.getJsonObject(2).getString("autoCreated"));
+
+      //ordered by filter desc
+      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "filter", "desc");
+      queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+      array = (JsonArray) queuesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of queues returned from query", 3, array.size());
+      Assert.assertEquals("queue2 ordered by filter", queueName2.toString(), array.getJsonObject(0).getString("name"));
+      Assert.assertEquals("queue1 ordered by filter", queueName1.toString(), array.getJsonObject(1).getString("name"));
+      Assert.assertEquals("queue3 ordered by filter", queueName3.toString(), array.getJsonObject(2).getString("name"));
+
+      //ordered by max consumers asc
+      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "maxConsumers", "asc");
+      queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+      array = (JsonArray) queuesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of queues returned from query", 3, array.size());
+      Assert.assertEquals("queue3 ordered by filter", queueName3.toString(), array.getJsonObject(0).getString("name"));
+      Assert.assertEquals("queue1 ordered by filter", queueName1.toString(), array.getJsonObject(1).getString("name"));
+      Assert.assertEquals("queue2 ordered by filter", queueName2.toString(), array.getJsonObject(2).getString("name"));
+
+      //ordering between the pages
+      //page 1
+      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "address", "desc");
+      queuesAsJsonString = serverControl.listQueues(filterString, 1, 1);
+      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+      array = (JsonArray) queuesAsJsonObject.get("data");
+      Assert.assertEquals("number of queues returned from query", 1, array.size());
+      Assert.assertEquals("queue3 ordered by page", queueName3.toString(), array.getJsonObject(0).getString("name"));
+
+      //page 2
       filterString = createJsonFilter("name", "CONTAINS", "my_queue", "address", "desc");
       queuesAsJsonString = serverControl.listQueues(filterString, 2, 1);
       queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
@@ -3118,292 +3724,1022 @@ public class ActiveMQServerControlTest extends ManagementTestBase {
       Assert.assertEquals("number of queues returned from query", 1, array.size());
       Assert.assertEquals("queue2 ordered by page", queueName2.toString(), array.getJsonObject(0).getString("name"));
 
-      //page 3
-      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "address", "desc");
-      queuesAsJsonString = serverControl.listQueues(filterString, 3, 1);
-      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-      array = (JsonArray) queuesAsJsonObject.get("data");
-      Assert.assertEquals("number of queues returned from query", 1, array.size());
-      Assert.assertEquals("queue1 ordered by page", queueName1.toString(), array.getJsonObject(0).getString("name"));
+      //page 3
+      filterString = createJsonFilter("name", "CONTAINS", "my_queue", "address", "desc");
+      queuesAsJsonString = serverControl.listQueues(filterString, 3, 1);
+      queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+      array = (JsonArray) queuesAsJsonObject.get("data");
+      Assert.assertEquals("number of queues returned from query", 1, array.size());
+      Assert.assertEquals("queue1 ordered by page", queueName1.toString(), array.getJsonObject(0).getString("name"));
+
+   }
+
+   @Test
+   public void testListQueuesNumericFilter() throws Exception {
+      SimpleString queueName1 = new SimpleString("my_queue_one");
+      SimpleString queueName2 = new SimpleString("my_queue_two");
+      SimpleString queueName3 = new SimpleString("one_consumer_queue_three");
+      SimpleString queueName4 = new SimpleString("my_queue_four");
+
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(queueName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName1, RoutingType.ANYCAST, queueName1, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      server.addAddressInfo(new AddressInfo(queueName2, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName2, RoutingType.ANYCAST, queueName2, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      server.addAddressInfo(new AddressInfo(queueName3, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName3, RoutingType.ANYCAST, queueName3, null, false, false, 10, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName3).setRoutingType(RoutingType.ANYCAST).setDurable(false).setMaxConsumers(10));
+      }
+
+      server.addAddressInfo(new AddressInfo(queueName4, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName4, RoutingType.ANYCAST, queueName4, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName4).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      // create some consumers
+      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator); ClientSession session = csf.createSession()) {
+
+         session.start();
+         ClientConsumer consumer1_q1 = session.createConsumer(queueName1);
+         ClientConsumer consumer2_q1 = session.createConsumer(queueName1);
+         ClientConsumer consumer1_q2 = session.createConsumer(queueName2);
+         ClientConsumer consumer2_q2 = session.createConsumer(queueName2);
+         ClientConsumer consumer3_q2 = session.createConsumer(queueName2);
+         ClientConsumer consumer1_q3 = session.createConsumer(queueName3);
+
+         ClientProducer clientProducer = session.createProducer(queueName1);
+         ClientMessage message = session.createMessage(false);
+         for (int i = 0; i < 10; i++) {
+            clientProducer.send(message);
+         }
+
+         //consume one message
+         ClientMessage messageReceived = consumer1_q1.receive(100);
+         if (messageReceived == null) {
+            fail("should have received a message");
+         }
+         messageReceived.acknowledge();
+         session.commit();
+
+         //test with CONTAINS returns nothing for numeric field
+         String filterString = createJsonFilter("CONSUMER_COUNT", "CONTAINS", "0");
+         String queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         JsonObject queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         JsonArray array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from query", 0, array.size());
+
+         //test with LESS_THAN returns 1 queue
+         filterString = createJsonFilter("CONSUMER_COUNT", "LESS_THAN", "1");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from LESS_THAN query", 1, array.size());
+         Assert.assertEquals("correct queue returned from query", queueName4.toString(), array.getJsonObject(0).getString("name"));
+
+         //test with GREATER_THAN returns 2 queue
+         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "2");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from GREATER_THAN query", 1, array.size());
+         Assert.assertEquals("correct queue returned from query", queueName2.toString(), array.getJsonObject(0).getString("name"));
+
+         //test with GREATER_THAN returns 2 queue
+         filterString = createJsonFilter("CONSUMER_COUNT", "EQUALS", "3");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from EQUALS query", 1, array.size());
+         Assert.assertEquals("correct queue returned from query", queueName2.toString(), array.getJsonObject(0).getString("name"));
+
+         //test with MESSAGE_COUNT returns 2 queue
+         filterString = createJsonFilter("MESSAGE_COUNT", "GREATER_THAN", "5");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from MESSAGE_COUNT query", 1, array.size());
+         Assert.assertEquals("correct queue returned from query", queueName1.toString(), array.getJsonObject(0).getString("name"));
+
+         //test with MESSAGE_ADDED returns 1 queue
+         filterString = createJsonFilter("MESSAGES_ADDED", "GREATER_THAN", "5");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from MESSAGE_COUNT query", 1, array.size());
+         Assert.assertEquals("correct queue returned from query", queueName1.toString(), array.getJsonObject(0).getString("name"));
+
+         //test with DELIVERING_COUNT returns 1 queue
+         filterString = createJsonFilter("DELIVERING_COUNT", "GREATER_THAN", "5");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from DELIVERING_COUNT query", 1, array.size());
+         Assert.assertEquals("correct queue returned from query", queueName1.toString(), array.getJsonObject(0).getString("name"));
+
+         //test with MESSAGE_ACKED returns 1 queue
+         filterString = createJsonFilter("MESSAGES_ACKED", "GREATER_THAN", "0");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from MESSAGES_ACKED query", 1, array.size());
+         Assert.assertEquals("correct queue returned from query", queueName1.toString(), array.getJsonObject(0).getString("name"));
+
+         //test with MAX_CONSUMERS returns 1 queue
+         filterString = createJsonFilter("MAX_CONSUMERS", "GREATER_THAN", "9");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from MAX_CONSUMERS query", 1, array.size());
+         Assert.assertEquals("correct queue returned from query", queueName3.toString(), array.getJsonObject(0).getString("name"));
+
+         //test with MESSAGES_KILLED returns 0 queue
+         filterString = createJsonFilter("MESSAGES_KILLED", "GREATER_THAN", "0");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from MESSAGES_KILLED query", 0, array.size());
+
+      }
+
+   }
+
+   @Test
+   public void testListQueuesNumericFilterInvalid() throws Exception {
+      SimpleString queueName1 = new SimpleString("my_queue_one");
+      SimpleString queueName2 = new SimpleString("one_consumer_queue_two");
+      SimpleString queueName3 = new SimpleString("one_consumer_queue_three");
+      SimpleString queueName4 = new SimpleString("my_queue_four");
+
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(queueName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName1, RoutingType.ANYCAST, queueName1, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      server.addAddressInfo(new AddressInfo(queueName2, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName2, RoutingType.ANYCAST, queueName2, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      server.addAddressInfo(new AddressInfo(queueName3, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName3, RoutingType.ANYCAST, queueName3, null, false, false, 10, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName3).setRoutingType(RoutingType.ANYCAST).setDurable(false).setMaxConsumers(10));
+      }
+
+      server.addAddressInfo(new AddressInfo(queueName4, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(queueName4, RoutingType.ANYCAST, queueName4, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName4).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      // create some consumers
+      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator); ClientSession session = csf.createSession()) {
+
+         session.start();
+         ClientConsumer consumer1_q1 = session.createConsumer(queueName1);
+         ClientConsumer consumer2_q1 = session.createConsumer(queueName1);
+
+         //test with CONTAINS returns nothing for numeric field
+         String filterString = createJsonFilter("CONSUMER_COUNT", "CONTAINS", "NOT_NUMBER");
+         String queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         JsonObject queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         JsonArray array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from query", 0, array.size());
+
+         //test with LESS_THAN and not a number
+         filterString = createJsonFilter("CONSUMER_COUNT", "LESS_THAN", "NOT_NUMBER");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from LESS_THAN query", 0, array.size());
+
+         //test with GREATER_THAN and not a number
+         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "NOT_NUMBER");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from GREATER_THAN query", 0, array.size());
+
+         //test with EQUALS and not number
+         filterString = createJsonFilter("CONSUMER_COUNT", "EQUALS", "NOT_NUMBER");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from EQUALS query", 0, array.size());
+
+         //test with LESS_THAN on string value returns no queue
+         filterString = createJsonFilter("name", "LESS_THAN", "my_queue");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from LESS_THAN on non numeric field", 0, array.size());
+
+         //test with GREATER_THAN on string value returns no queue
+         filterString = createJsonFilter("name", "GREATER_THAN", "my_queue");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from GREATER_THAN on non numeric field", 0, array.size());
+
+         //test with GREATER_THAN and empty string
+         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", " ");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from GREATER_THAN query", 0, array.size());
+
+         //test with CONSUMER_COUNT against a float value
+         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "0.12");
+         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+
+         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
+         array = (JsonArray) queuesAsJsonObject.get("data");
+         Assert.assertEquals("number of queues returned from GREATER_THAN query", 0, array.size());
+
+      }
+
+   }
+
+   @Test
+   public void testListAddresses() throws Exception {
+      SimpleString queueName1 = new SimpleString("my_queue_one");
+      SimpleString queueName2 = new SimpleString("my_queue_two");
+      SimpleString queueName3 = new SimpleString("other_queue_three");
+      SimpleString queueName4 = new SimpleString("other_queue_four");
+
+      SimpleString addressName1 = new SimpleString("my_address_one");
+      SimpleString addressName2 = new SimpleString("my_address_two");
+      SimpleString addressName3 = new SimpleString("other_address_three");
+
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+      server.addAddressInfo(new AddressInfo(addressName2, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName2, RoutingType.ANYCAST, queueName2, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName2).setAddress(addressName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+      server.addAddressInfo(new AddressInfo(addressName3, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName3, RoutingType.ANYCAST, queueName3, null, false, false);
+         server.createQueue(addressName3, RoutingType.ANYCAST, queueName4, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName3).setAddress(addressName3).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+         server.createQueue(new QueueConfiguration(queueName4).setAddress(addressName3).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      //test with CONTAINS filter
+      String filterString = createJsonFilter("name", "CONTAINS", "my_address");
+      String addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
+      JsonObject addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
+      JsonArray array = (JsonArray) addressesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of addresses returned from query", 2, array.size());
+      Assert.assertTrue("address name check", array.getJsonObject(0).getString("name").contains("my_address"));
+      Assert.assertTrue("address name check", array.getJsonObject(1).getString("name").contains("my_address"));
+
+      //test with EQUALS filter
+      filterString = createJsonFilter("name", "EQUALS", addressName1.toString());
+      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
+      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
+      array = (JsonArray) addressesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of addresses returned from query", 1, array.size());
+      //check all field names
+      Assert.assertEquals("address name check", addressName1.toString(), array.getJsonObject(0).getString("name"));
+      Assert.assertNotEquals("id", "", array.getJsonObject(0).getString("id"));
+      Assert.assertTrue("routingTypes", array.getJsonObject(0).getString("routingTypes").contains(RoutingType.ANYCAST.name()));
+      Assert.assertEquals("queueCount", "1", array.getJsonObject(0).getString("queueCount"));
+
+      //test with empty filter - all addresses should be returned
+      filterString = createJsonFilter("", "", "");
+      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
+      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
+      array = (JsonArray) addressesAsJsonObject.get("data");
+
+      Assert.assertTrue("number of addresses returned from query", 3 <= array.size());
+
+      //test with small page size
+      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 1);
+      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
+      array = (JsonArray) addressesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of queues returned from query", 1, array.size());
+
+      //test with QUEUE_COUNT with GREATER_THAN filter
+      filterString = createJsonFilter("QUEUE_COUNT", "GREATER_THAN", "1");
+      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
+      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
+      array = (JsonArray) addressesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of addresses returned from query", 1, array.size());
+      Assert.assertEquals("address name check", addressName3.toString(), array.getJsonObject(0).getString("name"));
+
+      //test with QUEUE_COUNT with LESS_THAN filter
+      filterString = createJsonFilter("QUEUE_COUNT", "LESS_THAN", "0");
+      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
+      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
+      array = (JsonArray) addressesAsJsonObject.get("data");
+
+      Assert.assertEquals("number of addresses returned from query", 0, array.size());
+
+   }
+
+   @Test
+   public void testListAddressOrder() throws Exception {
+
+      SimpleString queueName1 = new SimpleString("my_queue_one");
+      SimpleString queueName2 = new SimpleString("my_queue_two");
+      SimpleString queueName3 = new SimpleString("other_queue_three");
+      SimpleString queueName4 = new SimpleString("other_queue_four");
+
+      SimpleString addressName1 = new SimpleString("my_address_1");
+      SimpleString addressName2 = new SimpleString("my_address_2");
+      SimpleString addressName3 = new SimpleString("my_address_3");
+
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+      server.addAddressInfo(new AddressInfo(addressName2, RoutingType.ANYCAST));
+      server.addAddressInfo(new AddressInfo(addressName3, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName3, RoutingType.ANYCAST, queueName3, null, false, false);
+         server.createQueue(addressName3, RoutingType.ANYCAST, queueName4, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName3).setAddress(addressName3).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+         server.createQueue(new QueueConfiguration(queueName4).setAddress(addressName3).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      //test default order
+      String filterString = createJsonFilter("name", "CONTAINS", "my");
+      String addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
+      JsonObject addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
+      JsonArray array = (JsonArray) addressesAsJsonObject.get("data");
+
+      Assert.assertEquals("number addresses returned", 3, array.size());
+      Assert.assertEquals("address1 default order", addressName1.toString(), array.getJsonObject(0).getString("name"));
+      Assert.assertEquals("address2 default order", addressName2.toString(), array.getJsonObject(1).getString("name"));
+      Assert.assertEquals("address3 default order", addressName3.toString(), array.getJsonObject(2).getString("name"));
+
+      //test  ordered by name desc
+      filterString = createJsonFilter("name", "CONTAINS", "my", "name", "desc");
+      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
+      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
+      array = (JsonArray) addressesAsJsonObject.get("data");
+
+      Assert.assertEquals("number addresses returned", 3, array.size());
+      Assert.assertEquals("address3 ordered by name", addressName3.toString(), array.getJsonObject(0).getString("name"));
+      Assert.assertEquals("address2 ordered by name", addressName2.toString(), array.getJsonObject(1).getString("name"));
+      Assert.assertEquals("address1 ordered by name", addressName1.toString(), array.getJsonObject(2).getString("name"));
+
+      //test  ordered by queue count asc
+      filterString = createJsonFilter("name", "CONTAINS", "my", "queueCount", "asc");
+      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
+      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
+      array = (JsonArray) addressesAsJsonObject.get("data");
+
+      Assert.assertEquals("number addresses returned", 3, array.size());
+      Assert.assertEquals("address2 ordered by queue count", addressName2.toString(), array.getJsonObject(0).getString("name"));
+      Assert.assertEquals("address1 ordered by queue count", addressName1.toString(), array.getJsonObject(1).getString("name"));
+      Assert.assertEquals("address3 ordered by queue count", addressName3.toString(), array.getJsonObject(2).getString("name"));
+   }
+
+   @Test
+   public void testListConsumers() throws Exception {
+      SimpleString queueName1 = new SimpleString("my_queue_one");
+      SimpleString queueName2 = new SimpleString("my_queue_two");
+      SimpleString queueName3 = new SimpleString("other_queue_three");
+      SimpleString addressName1 = new SimpleString("my_address_one");
+      SimpleString addressName2 = new SimpleString("my_address_two");
+
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      server.addAddressInfo(new AddressInfo(addressName2, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName2, RoutingType.ANYCAST, queueName2, null, false, false);
+         server.createQueue(addressName2, RoutingType.ANYCAST, queueName3, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName2).setAddress(addressName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+         server.createQueue(new QueueConfiguration(queueName3).setAddress(addressName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      // create some consumers
+      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator); ClientSession session = csf.createSession()) {
+
+         ClientConsumer consumer1_q1 = session.createConsumer(queueName1);
+         ClientConsumer consumer2_q1 = session.createConsumer(queueName1);
+         ClientConsumer consumer1_q2 = session.createConsumer(queueName2);
+         ClientConsumer consumer1_q3 = session.createConsumer(queueName3);
+
+         //test with filter  EQUALS
+         String filterString = createJsonFilter("queue", "EQUALS", queueName1.toString());
+         String consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
+         JsonObject consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
+         JsonArray array = (JsonArray) consumersAsJsonObject.get("data");
+
+         Assert.assertEquals("number of consumers returned from query", 2, array.size());
+         Assert.assertEquals("check consumer's queue", queueName1.toString(), array.getJsonObject(0).getString(ConsumerField.QUEUE.getName()));
+         Assert.assertEquals("check consumer's queue", queueName1.toString(), array.getJsonObject(0).getString(ConsumerField.QUEUE.getName()));
+
+         // test with a CONTAINS operation
+         filterString = createJsonFilter(ConsumerField.QUEUE.getName(), "CONTAINS", "my_queue");
+         consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
+         consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
+         array = (JsonArray) consumersAsJsonObject.get("data");
+
+         Assert.assertEquals("number of consumers returned from query", 3, array.size());
+
+         // filter by address
+         filterString = createJsonFilter(ConsumerField.ADDRESS.getName(),  "EQUALS", addressName1.toString());
+         consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
+         consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
+         array = (JsonArray) consumersAsJsonObject.get("data");
+
+         Assert.assertEquals("number of consumers returned from query", 2, array.size());
+         Assert.assertEquals("check consumers address", addressName1.toString(), array.getJsonObject(0).getString(ConsumerField.ADDRESS.getName()));
+         Assert.assertEquals("check consumers address", addressName1.toString(), array.getJsonObject(1).getString(ConsumerField.ADDRESS.getName()));
+
+         //test with empty filter - all consumers should be returned
+         filterString = createJsonFilter("", "", "");
+         consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
+         consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
+         array = (JsonArray) consumersAsJsonObject.get("data");
+
+         Assert.assertTrue("at least 4 consumers returned from query", 4 <= array.size());
+
+         //test with small page size
+         consumersAsJsonString = serverControl.listConsumers(filterString, 1, 1);
+         consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
+         array = (JsonArray) consumersAsJsonObject.get("data");
+
+         Assert.assertEquals("number of consumers returned from query", 1, array.size());
+
+         //test contents of returned consumer
+         filterString = createJsonFilter(ConsumerField.QUEUE.getName(), "EQUALS", queueName3.toString());
+         consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
+         consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
+         array = (JsonArray) consumersAsJsonObject.get("data");
+
+         Assert.assertEquals("number of consumers returned from query", 1, array.size());
+         JsonObject jsonConsumer = array.getJsonObject(0);
+         Assert.assertEquals("queue name in consumer", queueName3.toString(), jsonConsumer.getString(ConsumerField.QUEUE.getName()));
+         Assert.assertEquals("address name in consumer", addressName2.toString(), jsonConsumer.getString(ConsumerField.ADDRESS.getName()));
+         Assert.assertEquals("consumer protocol ", "CORE", jsonConsumer.getString(ConsumerField.PROTOCOL.getName()));
+         Assert.assertEquals("queue type", "anycast", jsonConsumer.getString(ConsumerField.QUEUE_TYPE.getName()));
+         Assert.assertNotEquals("id", "", jsonConsumer.getString(ConsumerField.ID.getName()));
+         Assert.assertNotEquals("session", "", jsonConsumer.getString(ConsumerField.SESSION.getName()));
+         Assert.assertEquals("clientID", "", jsonConsumer.getString(ConsumerField.CLIENT_ID.getName()));
+         Assert.assertEquals("user", "", jsonConsumer.getString(ConsumerField.USER.getName()));
+         Assert.assertNotEquals("localAddress", "", jsonConsumer.getString(ConsumerField.LOCAL_ADDRESS.getName()));
+         Assert.assertNotEquals("remoteAddress", "", jsonConsumer.getString(ConsumerField.REMOTE_ADDRESS.getName()));
+         Assert.assertNotEquals("creationTime", "", jsonConsumer.getString(ConsumerField.CREATION_TIME.getName()));
+         Assert.assertNotEquals("messagesInTransit", "", jsonConsumer.getString(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
+         Assert.assertNotEquals("messagesInTransitSize", "", jsonConsumer.getString(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()));
+         Assert.assertNotEquals("messagesDelivered", "", jsonConsumer.getString(ConsumerField.MESSAGES_DELIVERED.getName()));
+         Assert.assertNotEquals("messagesDeliveredSize", "", jsonConsumer.getString(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()));
+         Assert.assertNotEquals("messagesAcknowledged", "", jsonConsumer.getString(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()));
+         Assert.assertEquals("lastDeliveredTime", 0, jsonConsumer.getInt(ConsumerField.LAST_DELIVERED_TIME.getName()));
+         Assert.assertEquals("lastAcknowledgedTime", 0, jsonConsumer.getInt(ConsumerField.LAST_ACKNOWLEDGED_TIME.getName()));
+      }
+
+   }
+
+   @Test
+   public void testListConsumersOrder() throws Exception {
+      SimpleString queueName1 = new SimpleString("my_queue_one");
+      SimpleString addressName1 = new SimpleString("my_address_one");
+
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator);) {
+
+         ClientSessionImpl session1 = (ClientSessionImpl) csf.createSession();
+         ClientSessionImpl session2 = (ClientSessionImpl) csf.createSession();
+         ClientSessionImpl session3 = (ClientSessionImpl) csf.createSession();
+
+         //sleep - test compares creationTimes
+         ClientConsumer consumer_s1 = session1.createConsumer(queueName1);
+         Thread.sleep(500);
+         ClientConsumer consumer_s2 = session2.createConsumer(queueName1);
+         Thread.sleep(500);
+         ClientConsumer consumer_s3 = session3.createConsumer(queueName1);
+
+         //test default Order
+         String filterString = createJsonFilter(ConsumerField.QUEUE.getName(), "EQUALS", queueName1.toString());
+         String consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
+         JsonObject consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
+         JsonArray array = (JsonArray) consumersAsJsonObject.get("data");
+         Assert.assertEquals("number of consumers returned from query", 3, array.size());
+
+         Assert.assertEquals("Consumer1 default order", session1.getName(), array.getJsonObject(0).getString(ConsumerField.SESSION.getName()));
+         Assert.assertEquals("Consumer2 default order", session2.getName(), array.getJsonObject(1).getString(ConsumerField.SESSION.getName()));
+         Assert.assertEquals("Consumer3 default order", session3.getName(), array.getJsonObject(2).getString(ConsumerField.SESSION.getName()));
+
+         //test ordered by creationTime
+         filterString = createJsonFilter(ConsumerField.QUEUE.getName(), "EQUALS", queueName1.toString(), "creationTime", "desc");
+         consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
+         consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
+         array = (JsonArray) consumersAsJsonObject.get("data");
+         Assert.assertEquals("number of consumers returned from query", 3, array.size());
+
+         Assert.assertEquals("Consumer3 creation time", session3.getName(), array.getJsonObject(0).getString(ConsumerField.SESSION.getName()));
+         Assert.assertEquals("Consumer2 creation time", session2.getName(), array.getJsonObject(1).getString(ConsumerField.SESSION.getName()));
+         Assert.assertEquals("Consumer1 creation time", session1.getName(), array.getJsonObject(2).getString(ConsumerField.SESSION.getName()));
+
+      }
+   }
+
+   @Test
+   public void testListSessions() throws Exception {
+      SimpleString queueName1 = new SimpleString("my_queue_one");
+      SimpleString addressName1 = new SimpleString("my_address_one");
+
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      // create some consumers
+      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator);) {
+
+         ClientSessionImpl session1 = (ClientSessionImpl) csf.createSession();
+         Thread.sleep(500);
+         ClientSessionImpl session2 = (ClientSessionImpl) csf.createSession();
+         Thread.sleep(500);
+         ClientSessionImpl session3 = (ClientSessionImpl) csf.createSession();
+         ClientConsumer consumer1_s1 = session1.createConsumer(queueName1);
+         ClientConsumer consumer2_s1 = session1.createConsumer(queueName1);
+
+         ClientConsumer consumer1_s2 = session2.createConsumer(queueName1);
+         ClientConsumer consumer2_s2 = session2.createConsumer(queueName1);
+         ClientConsumer consumer3_s2 = session2.createConsumer(queueName1);
+         ClientConsumer consumer4_s2 = session2.createConsumer(queueName1);
+
+         ClientConsumer consumer1_s3 = session3.createConsumer(queueName1);
+         ClientConsumer consumer2_s3 = session3.createConsumer(queueName1);
+         ClientConsumer consumer3_s3 = session3.createConsumer(queueName1);
+
+         String filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "1");
+         String sessionsAsJsonString = serverControl.listSessions(filterString, 1, 50);
+         JsonObject sessionsAsJsonObject = JsonUtil.readJsonObject(sessionsAsJsonString);
+         JsonArray array = (JsonArray) sessionsAsJsonObject.get("data");
+
+
+         Assert.assertEquals("number of sessions returned from query", 3, array.size());
+         JsonObject jsonSession = array.getJsonObject(0);
+
+         //check all fields
+         Assert.assertNotEquals("id", "", jsonSession.getString("id"));
+         Assert.assertEquals("user", "", jsonSession.getString("user"));
+         Assert.assertNotEquals("creationTime", "", jsonSession.getString("creationTime"));
+         Assert.assertEquals("consumerCount", 2, jsonSession.getInt("consumerCount"));
+         Assert.assertTrue("producerCount", 0 <= jsonSession.getInt("producerCount"));
+         Assert.assertNotEquals("connectionID", "", jsonSession.getString("connectionID"));
+
+         //check default order
+         Assert.assertEquals("session1 location", session1.getName(), array.getJsonObject(0).getString("id"));
+         Assert.assertEquals("session2 location", session2.getName(), array.getJsonObject(1).getString("id"));
+         Assert.assertEquals("session3 location", session3.getName(), array.getJsonObject(2).getString("id"));
+
+         //bring back session ordered by consumer count
+         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "1", "consumerCount", "asc");
+         sessionsAsJsonString = serverControl.listSessions(filterString, 1, 50);
+         sessionsAsJsonObject = JsonUtil.readJsonObject(sessionsAsJsonString);
+         array = (JsonArray) sessionsAsJsonObject.get("data");
+
+         Assert.assertTrue("number of sessions returned from query", 3 == array.size());
+         Assert.assertEquals("session1 ordered by consumer", session1.getName(), array.getJsonObject(0).getString("id"));
+         Assert.assertEquals("session3 ordered by consumer", session3.getName(), array.getJsonObject(1).getString("id"));
+         Assert.assertEquals("session2 ordered by consumer", session2.getName(), array.getJsonObject(2).getString("id"));
+
+         //bring back session ordered by consumer Count
+         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "1", "consumerCount", "asc");
+         sessionsAsJsonString = serverControl.listSessions(filterString, 1, 50);
+         sessionsAsJsonObject = JsonUtil.readJsonObject(sessionsAsJsonString);
+         array = (JsonArray) sessionsAsJsonObject.get("data");
+
+         Assert.assertTrue("number of sessions returned from query", 3 == array.size());
+         Assert.assertEquals("session1 ordered by consumer", session1.getName(), array.getJsonObject(0).getString("id"));
+         Assert.assertEquals("session3 ordered by consumer", session3.getName(), array.getJsonObject(1).getString("id"));
+         Assert.assertEquals("session2 ordered by consumer", session2.getName(), array.getJsonObject(2).getString("id"));
+
+         //bring back session ordered by creation time (desc)
+         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "1", "creationTime", "desc");
+         sessionsAsJsonString = serverControl.listSessions(filterString, 1, 50);
+         sessionsAsJsonObject = JsonUtil.readJsonObject(sessionsAsJsonString);
+         array = (JsonArray) sessionsAsJsonObject.get("data");
+
+         Assert.assertTrue("number of sessions returned from query", 3 == array.size());
+         Assert.assertEquals("session3 ordered by creationTime", session3.getName(), array.getJsonObject(0).getString("id"));
+         Assert.assertEquals("session2 ordered by creationTime", session2.getName(), array.getJsonObject(1).getString("id"));
+         Assert.assertEquals("session1 ordered by creationTime", session1.getName(), array.getJsonObject(2).getString("id"));
+
+      }
+   }
+
+   @RetryMethod(retries = 2) // the list of connections eventually comes from a hashmap on a different order. Which is fine but makes the test fail. a Retry is ok
+   @Test
+   public void testListConnections() throws Exception {
+      SimpleString queueName1 = new SimpleString("my_queue_one");
+      SimpleString addressName1 = new SimpleString("my_address_one");
+
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      ClientSessionFactoryImpl csf = null;
+      ClientSessionFactoryImpl csf2 = null;
+      ClientSessionFactoryImpl csf3 = null;
+
+      // create some consumers
+      try (ServerLocator locator = createInVMNonHALocator()) {
+
+         //sleep as test compares creationTime
+         csf = (ClientSessionFactoryImpl) createSessionFactory(locator);
+         Thread.sleep(50);
+         csf2 = (ClientSessionFactoryImpl) createSessionFactory(locator);
+         Thread.sleep(50);
+         csf3 = (ClientSessionFactoryImpl) createSessionFactory(locator);
+
+         ClientSession session1_c1 = csf.createSession("guest", "guest", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
+         ClientSession session2_c1 = csf.createSession("guest", "guest", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
+
+         ClientSession session1_c2 = csf2.createSession("myUser", "myPass", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
+         ClientSession session2_c2 = csf2.createSession("myUser", "myPass", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
+         ClientSession session3_c2 = csf2.createSession("myUser", "myPass", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
+         ClientSession session4_c2 = csf2.createSession("myUser", "myPass", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
+
+         ClientSession session1_c4 = csf3.createSession("myUser", "myPass", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
+         ClientSession session2_c4 = csf3.createSession("guest", "guest", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
+         ClientSession session3_c4 = csf3.createSession("guest", "guest", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
+
+         String filterString = createJsonFilter("SESSION_COUNT", "GREATER_THAN", "1");
+         String connectionsAsJsonString = serverControl.listConnections(filterString, 1, 50);
+         System.err.println(connectionsAsJsonString);
+         JsonObject connectionsAsJsonObject = JsonUtil.readJsonObject(connectionsAsJsonString);
+         JsonArray array = (JsonArray) connectionsAsJsonObject.get("data");
+
+         Assert.assertEquals("number of connections returned from query", 3, array.size());
+         JsonObject jsonConnection = array.getJsonObject(0);
+
+         //check all fields
+         Assert.assertNotEquals("connectionID", "", jsonConnection.getString("connectionID"));
+         Assert.assertNotEquals("remoteAddress", "", jsonConnection.getString("remoteAddress"));
+         Assert.assertEquals("users", "guest", jsonConnection.getString("users"));
+         Assert.assertNotEquals("creationTime", "", jsonConnection.getString("creationTime"));
+         Assert.assertNotEquals("implementation", "", jsonConnection.getString("implementation"));
+         Assert.assertNotEquals("protocol", "", jsonConnection.getString("protocol"));
+         Assert.assertEquals("clientID", "", jsonConnection.getString("clientID"));
+         Assert.assertNotEquals("localAddress", "", jsonConnection.getString("localAddress"));
+         Assert.assertEquals("sessionCount", 2, jsonConnection.getInt("sessionCount"));
+
+         //check default order
+         Assert.assertEquals("connection1 default Order", csf.getConnection().getID(), array.getJsonObject(0).getString("connectionID"));
+         Assert.assertEquals("connection2 default Order", csf2.getConnection().getID(), array.getJsonObject(1).getString("connectionID"));
+         Assert.assertEquals("connection3 session Order", csf3.getConnection().getID(), array.getJsonObject(2).getString("connectionID"));
+
+         //check order by users asc
+         filterString = createJsonFilter("SESSION_COUNT", "GREATER_THAN", "1", "users", "asc");
+         connectionsAsJsonString = serverControl.listConnections(filterString, 1, 50);
+         connectionsAsJsonObject = JsonUtil.readJsonObject(connectionsAsJsonString);
+         array = (JsonArray) connectionsAsJsonObject.get("data");
+
+         Assert.assertEquals("number of connections returned from query", 3, array.size());
+         Assert.assertEquals("connection1 users Order", "guest", array.getJsonObject(0).getString("users"));
+         Assert.assertEquals("connection3 users Order", "guest,myUser", array.getJsonObject(1).getString("users"));
+         Assert.assertEquals("connection2 users Order", "myUser", array.getJsonObject(2).getString("users"));
+
+         //check order by users desc
+         filterString = createJsonFilter("SESSION_COUNT", "GREATER_THAN", "1", "users", "desc");
+         connectionsAsJsonString = serverControl.listConnections(filterString, 1, 50);
+         connectionsAsJsonObject = JsonUtil.readJsonObject(connectionsAsJsonString);
+         array = (JsonArray) connectionsAsJsonObject.get("data");
+
+         Assert.assertEquals("number of connections returned from query", 3, array.size());
+         Assert.assertEquals("connection2 users Order", "myUser", array.getJsonObject(0).getString("users"));
+         Assert.assertEquals("connection3 users Order", "guest,myUser", array.getJsonObject(1).getString("users"));
+         Assert.assertEquals("connection1 users Order", "guest", array.getJsonObject(2).getString("users"));
+
+         //check order by session count desc
+         filterString = createJsonFilter("SESSION_COUNT", "GREATER_THAN", "1", "sessionCount", "desc");
+         connectionsAsJsonString = serverControl.listConnections(filterString, 1, 50);
+         connectionsAsJsonObject = JsonUtil.readJsonObject(connectionsAsJsonString);
+         array = (JsonArray) connectionsAsJsonObject.get("data");
+
+         Assert.assertEquals("number of connections returned from query", 3, array.size());
+         Assert.assertEquals("connection2 session Order", csf2.getConnection().getID(), array.getJsonObject(0).getString("connectionID"));
+         Assert.assertEquals("connection3 session Order", csf3.getConnection().getID(), array.getJsonObject(1).getString("connectionID"));
+         Assert.assertEquals("connection1 session Order", csf.getConnection().getID(), array.getJsonObject(2).getString("connectionID"));
+
+         //check order by creationTime desc
+         filterString = createJsonFilter("SESSION_COUNT", "GREATER_THAN", "1", "creationTime", "desc");
+         connectionsAsJsonString = serverControl.listConnections(filterString, 1, 50);
+         connectionsAsJsonObject = JsonUtil.readJsonObject(connectionsAsJsonString);
+         array = (JsonArray) connectionsAsJsonObject.get("data");
 
+         Assert.assertEquals("number of connections returned from query", 3, array.size());
+         Assert.assertEquals("connection3 creationTime Order", csf3.getConnection().getID(), array.getJsonObject(0).getString("connectionID"));
+         Assert.assertEquals("connection2 creationTime Order", csf2.getConnection().getID(), array.getJsonObject(1).getString("connectionID"));
+         Assert.assertEquals("connection1 creationTime Order", csf.getConnection().getID(), array.getJsonObject(2).getString("connectionID"));
+      } finally {
+         if (csf != null) {
+            csf.close();
+         }
+         if (csf2 != null) {
+            csf.close();
+         }
+         if (csf3 != null) {
+            csf.close();
+         }
+      }
    }
 
    @Test
-   public void testListQueuesNumericFilter() throws Exception {
+   public void testListConnectionsClientID() throws Exception {
       SimpleString queueName1 = new SimpleString("my_queue_one");
-      SimpleString queueName2 = new SimpleString("my_queue_two");
-      SimpleString queueName3 = new SimpleString("one_consumer_queue_three");
-      SimpleString queueName4 = new SimpleString("my_queue_four");
+      SimpleString addressName1 = new SimpleString("my_address_one");
 
       ActiveMQServerControl serverControl = createManagementControl();
 
-      server.addAddressInfo(new AddressInfo(queueName1, RoutingType.ANYCAST));
-      if (legacyCreateQueue) {
-         server.createQueue(queueName1, RoutingType.ANYCAST, queueName1, null, false, false);
-      } else {
-         server.createQueue(new QueueConfiguration(queueName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
-      }
-
-      server.addAddressInfo(new AddressInfo(queueName2, RoutingType.ANYCAST));
-      if (legacyCreateQueue) {
-         server.createQueue(queueName2, RoutingType.ANYCAST, queueName2, null, false, false);
-      } else {
-         server.createQueue(new QueueConfiguration(queueName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
-      }
-
-      server.addAddressInfo(new AddressInfo(queueName3, RoutingType.ANYCAST));
+      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
       if (legacyCreateQueue) {
-         server.createQueue(queueName3, RoutingType.ANYCAST, queueName3, null, false, false, 10, false, false);
+         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
       } else {
-         server.createQueue(new QueueConfiguration(queueName3).setRoutingType(RoutingType.ANYCAST).setDurable(false).setMaxConsumers(10));
+         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
 
-      server.addAddressInfo(new AddressInfo(queueName4, RoutingType.ANYCAST));
-      if (legacyCreateQueue) {
-         server.createQueue(queueName4, RoutingType.ANYCAST, queueName4, null, false, false);
-      } else {
-         server.createQueue(new QueueConfiguration(queueName4).setRoutingType(RoutingType.ANYCAST).setDurable(false));
-      }
+      ClientSessionFactoryImpl csf = null;
 
       // create some consumers
-      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator); ClientSession session = csf.createSession()) {
+      try (ServerLocator locator = createInVMNonHALocator()) {
+         //sleep as test compares creationTime
+         csf = (ClientSessionFactoryImpl) createSessionFactory(locator);
+         ClientSession session1_c1 = csf.createSession();
+         ClientSession session2_c1 = csf.createSession();
+         session1_c1.addMetaData(ClientSession.JMS_SESSION_IDENTIFIER_PROPERTY, "");
+         session1_c1.addMetaData(ClientSession.JMS_SESSION_CLIENT_ID_PROPERTY, "MYClientID");
 
-         session.start();
-         ClientConsumer consumer1_q1 = session.createConsumer(queueName1);
-         ClientConsumer consumer2_q1 = session.createConsumer(queueName1);
-         ClientConsumer consumer1_q2 = session.createConsumer(queueName2);
-         ClientConsumer consumer2_q2 = session.createConsumer(queueName2);
-         ClientConsumer consumer3_q2 = session.createConsumer(queueName2);
-         ClientConsumer consumer1_q3 = session.createConsumer(queueName3);
+         String filterString = createJsonFilter("SESSION_COUNT", "GREATER_THAN", "1");
+         String connectionsAsJsonString = serverControl.listConnections(filterString, 1, 50);
+         JsonObject connectionsAsJsonObject = JsonUtil.readJsonObject(connectionsAsJsonString);
+         JsonArray array = (JsonArray) connectionsAsJsonObject.get("data");
 
-         ClientProducer clientProducer = session.createProducer(queueName1);
-         ClientMessage message = session.createMessage(false);
-         for (int i = 0; i < 10; i++) {
-            clientProducer.send(message);
-         }
+         Assert.assertEquals("number of connections returned from query", 1, array.size());
+         JsonObject jsonConnection = array.getJsonObject(0);
 
-         //consume one message
-         ClientMessage messageReceived = consumer1_q1.receive(100);
-         if (messageReceived == null) {
-            fail("should have received a message");
+         //check all fields
+         Assert.assertEquals("clientID", "MYClientID", jsonConnection.getString("clientID"));
+      } finally {
+         if (csf != null) {
+            csf.close();
          }
-         messageReceived.acknowledge();
-         session.commit();
-
-         //test with CONTAINS returns nothing for numeric field
-         String filterString = createJsonFilter("CONSUMER_COUNT", "CONTAINS", "0");
-         String queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
-
-         JsonObject queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         JsonArray array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from query", 0, array.size());
-
-         //test with LESS_THAN returns 1 queue
-         filterString = createJsonFilter("CONSUMER_COUNT", "LESS_THAN", "1");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
-
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from LESS_THAN query", 1, array.size());
-         Assert.assertEquals("correct queue returned from query", queueName4.toString(), array.getJsonObject(0).getString("name"));
-
-         //test with GREATER_THAN returns 2 queue
-         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "2");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
-
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from GREATER_THAN query", 1, array.size());
-         Assert.assertEquals("correct queue returned from query", queueName2.toString(), array.getJsonObject(0).getString("name"));
-
-         //test with GREATER_THAN returns 2 queue
-         filterString = createJsonFilter("CONSUMER_COUNT", "EQUALS", "3");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+      }
+   }
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from EQUALS query", 1, array.size());
-         Assert.assertEquals("correct queue returned from query", queueName2.toString(), array.getJsonObject(0).getString("name"));
+   @Test
+   public void testListProducers() throws Exception {
+      SimpleString queueName1 = new SimpleString("my_queue_one");
+      SimpleString addressName1 = new SimpleString("my_address_one");
 
-         //test with MESSAGE_COUNT returns 2 queue
-         filterString = createJsonFilter("MESSAGE_COUNT", "GREATER_THAN", "5");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+      ActiveMQServerControl serverControl = createManagementControl();
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from MESSAGE_COUNT query", 1, array.size());
-         Assert.assertEquals("correct queue returned from query", queueName1.toString(), array.getJsonObject(0).getString("name"));
+      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
 
-         //test with MESSAGE_ADDED returns 1 queue
-         filterString = createJsonFilter("MESSAGES_ADDED", "GREATER_THAN", "5");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+      // create some consumers
+      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator);) {
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from MESSAGE_COUNT query", 1, array.size());
-         Assert.assertEquals("correct queue returned from query", queueName1.toString(), array.getJsonObject(0).getString("name"));
+         ClientSession session1 = csf.createSession();
+         ClientSession session2 = csf.createSession();
 
-         //test with DELIVERING_COUNT returns 1 queue
-         filterString = createJsonFilter("DELIVERING_COUNT", "GREATER_THAN", "5");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+         ClientProducer producer1 = session1.createProducer(addressName1);
+         producer1.send(session1.createMessage(true));
+         ClientProducer producer2 = session2.createProducer(addressName1);
+         producer2.send(session2.createMessage(true));
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from DELIVERING_COUNT query", 1, array.size());
-         Assert.assertEquals("correct queue returned from query", queueName1.toString(), array.getJsonObject(0).getString("name"));
+         //bring back all producers
+         String filterString = createJsonFilter("", "", "");
+         String producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         JsonArray array = (JsonArray) producersAsJsonObject.get("data");
 
-         //test with MESSAGE_ACKED returns 1 queue
-         filterString = createJsonFilter("MESSAGES_ACKED", "GREATER_THAN", "0");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+         Assert.assertEquals("number of producers returned from query", 2 + extraProducers, array.size());
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from MESSAGES_ACKED query", 1, array.size());
-         Assert.assertEquals("correct queue returned from query", queueName1.toString(), array.getJsonObject(0).getString("name"));
+         boolean foundElement = false;
+         for (int i = 0; i < array.size(); i++) {
 
-         //test with MAX_CONSUMERS returns 1 queue
-         filterString = createJsonFilter("MAX_CONSUMERS", "GREATER_THAN", "9");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+            JsonObject jsonSession = array.getJsonObject(i);
+            if (jsonSession.getString("address").equals("activemq.management")) {
+               continue;
+            }
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from MAX_CONSUMERS query", 1, array.size());
-         Assert.assertEquals("correct queue returned from query", queueName3.toString(), array.getJsonObject(0).getString("name"));
+            foundElement = true;
 
-         //test with MESSAGES_KILLED returns 0 queue
-         filterString = createJsonFilter("MESSAGES_KILLED", "GREATER_THAN", "0");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+            //check all fields
+            Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+            Assert.assertNotEquals(ProducerField.SESSION.getName(), "", jsonSession.getString(ProducerField.SESSION.getName()));
+            Assert.assertEquals(ProducerField.CLIENT_ID.getName(), "", jsonSession.getString(ProducerField.CLIENT_ID.getName()));
+            Assert.assertEquals(ProducerField.USER.getName(), "", jsonSession.getString(ProducerField.USER.getName()));
+            Assert.assertNotEquals(ProducerField.PROTOCOL.getName(), "", jsonSession.getString(ProducerField.PROTOCOL.getName()));
+            Assert.assertEquals(ProducerField.ADDRESS.getName(), addressName1.toString(), jsonSession.getString(ProducerField.ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", jsonSession.getString(ProducerField.LOCAL_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", jsonSession.getString(ProducerField.REMOTE_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         }
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from MESSAGES_KILLED query", 0, array.size());
 
+         Assert.assertTrue("Valid session not found", foundElement);
       }
-
    }
 
    @Test
-   public void testListQueuesNumericFilterInvalid() throws Exception {
+   public void testListProducersLargeMessages() throws Exception {
       SimpleString queueName1 = new SimpleString("my_queue_one");
-      SimpleString queueName2 = new SimpleString("one_consumer_queue_two");
-      SimpleString queueName3 = new SimpleString("one_consumer_queue_three");
-      SimpleString queueName4 = new SimpleString("my_queue_four");
+      SimpleString addressName1 = new SimpleString("my_address_one");
 
       ActiveMQServerControl serverControl = createManagementControl();
 
-      server.addAddressInfo(new AddressInfo(queueName1, RoutingType.ANYCAST));
-      if (legacyCreateQueue) {
-         server.createQueue(queueName1, RoutingType.ANYCAST, queueName1, null, false, false);
-      } else {
-         server.createQueue(new QueueConfiguration(queueName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
-      }
-
-      server.addAddressInfo(new AddressInfo(queueName2, RoutingType.ANYCAST));
-      if (legacyCreateQueue) {
-         server.createQueue(queueName2, RoutingType.ANYCAST, queueName2, null, false, false);
-      } else {
-         server.createQueue(new QueueConfiguration(queueName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
-      }
-
-      server.addAddressInfo(new AddressInfo(queueName3, RoutingType.ANYCAST));
-      if (legacyCreateQueue) {
-         server.createQueue(queueName3, RoutingType.ANYCAST, queueName3, null, false, false, 10, false, false);
-      } else {
-         server.createQueue(new QueueConfiguration(queueName3).setRoutingType(RoutingType.ANYCAST).setDurable(false).setMaxConsumers(10));
-      }
-
-      server.addAddressInfo(new AddressInfo(queueName4, RoutingType.ANYCAST));
+      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
       if (legacyCreateQueue) {
-         server.createQueue(queueName4, RoutingType.ANYCAST, queueName4, null, false, false);
+         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
       } else {
-         server.createQueue(new QueueConfiguration(queueName4).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
 
       // create some consumers
-      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator); ClientSession session = csf.createSession()) {
+      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator);) {
 
-         session.start();
-         ClientConsumer consumer1_q1 = session.createConsumer(queueName1);
-         ClientConsumer consumer2_q1 = session.createConsumer(queueName1);
+         ClientSession session1 = csf.createSession();
+         ClientSession session2 = csf.createSession();
+
+         ClientProducer producer1 = session1.createProducer(addressName1);
+         producer1.send(session1.createMessage(true));
+         ClientProducer producer2 = session2.createProducer(addressName1);
+         producer2.send(session2.createMessage(true));
 
-         //test with CONTAINS returns nothing for numeric field
-         String filterString = createJsonFilter("CONSUMER_COUNT", "CONTAINS", "NOT_NUMBER");
-         String queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+         //bring back all producers
+         String filterString = createJsonFilter("", "", "");
+         String producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         JsonArray array = (JsonArray) producersAsJsonObject.get("data");
 
-         JsonObject queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         JsonArray array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from query", 0, array.size());
+         Assert.assertEquals("number of producers returned from query", 2 + extraProducers, array.size());
 
-         //test with LESS_THAN and not a number
-         filterString = createJsonFilter("CONSUMER_COUNT", "LESS_THAN", "NOT_NUMBER");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+         boolean foundElement = false;
+         for (int i = 0; i < array.size(); i++) {
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from LESS_THAN query", 0, array.size());
+            JsonObject jsonSession = array.getJsonObject(i);
+            if (jsonSession.getString("address").equals("activemq.management")) {
+               continue;
+            }
 
-         //test with GREATER_THAN and not a number
-         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "NOT_NUMBER");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+            foundElement = true;
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from GREATER_THAN query", 0, array.size());
+            //check all fields
+            Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+            Assert.assertNotEquals(ProducerField.SESSION.getName(), "", jsonSession.getString(ProducerField.SESSION.getName()));
+            Assert.assertEquals(ProducerField.CLIENT_ID.getName(), "", jsonSession.getString(ProducerField.CLIENT_ID.getName()));
+            Assert.assertEquals(ProducerField.USER.getName(), "", jsonSession.getString(ProducerField.USER.getName()));
+            Assert.assertNotEquals(ProducerField.PROTOCOL.getName(), "", jsonSession.getString(ProducerField.PROTOCOL.getName()));
+            Assert.assertEquals(ProducerField.ADDRESS.getName(), addressName1.toString(), jsonSession.getString(ProducerField.ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", jsonSession.getString(ProducerField.LOCAL_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", jsonSession.getString(ProducerField.REMOTE_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         }
 
-         //test with EQUALS and not number
-         filterString = createJsonFilter("CONSUMER_COUNT", "EQUALS", "NOT_NUMBER");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from EQUALS query", 0, array.size());
+         Assert.assertTrue("Valid session not found", foundElement);
+      }
+   }
 
-         //test with LESS_THAN on string value returns no queue
-         filterString = createJsonFilter("name", "LESS_THAN", "my_queue");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+   @Test
+   public void testListProducersAsJSONAgainstServer() throws Exception {
+      SimpleString queueName1 = new SimpleString("my_queue_one");
+      SimpleString addressName1 = new SimpleString("my_address_one");
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from LESS_THAN on non numeric field", 0, array.size());
+      ActiveMQServerControl serverControl = createManagementControl();
 
-         //test with GREATER_THAN on string value returns no queue
-         filterString = createJsonFilter("name", "GREATER_THAN", "my_queue");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from GREATER_THAN on non numeric field", 0, array.size());
+      // create some consumers
+      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator);) {
 
-         //test with GREATER_THAN and empty string
-         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", " ");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+         ClientSession session1 = csf.createSession();
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from GREATER_THAN query", 0, array.size());
+         ClientProducer producer1 = session1.createProducer(addressName1);
+         producer1.send(session1.createMessage(true));
 
-         //test with CONSUMER_COUNT against a float value
-         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "0.12");
-         queuesAsJsonString = serverControl.listQueues(filterString, 1, 50);
+         //bring back all producers
+         String producersAsJsonString = serverControl.listProducersInfoAsJSON();
+         JsonArray array = JsonUtil.readJsonArray(producersAsJsonString);
 
-         queuesAsJsonObject = JsonUtil.readJsonObject(queuesAsJsonString);
-         array = (JsonArray) queuesAsJsonObject.get("data");
-         Assert.assertEquals("number of queues returned from GREATER_THAN query", 0, array.size());
+         Assert.assertEquals("number of producers returned from query", 1 + extraProducers, array.size());
 
-      }
+         JsonObject jsonSession = array.getJsonObject(0);
+         if (!jsonSession.getString(ProducerField.ADDRESS.getAlternativeName()).equalsIgnoreCase(addressName1.toString())) {
+            jsonSession = array.getJsonObject(1);
+         }
 
+         //get the only server producer
+         ServerProducer producer = server.getSessionByID(jsonSession.getString(ProducerField.SESSION.getAlternativeName())).getServerProducers().iterator().next();
+         //check all fields
+         Assert.assertEquals(ProducerField.ID.getName(), String.valueOf(producer.getID()), jsonSession.getString(ProducerField.ID.getName()));
+         Assert.assertEquals(ProducerField.NAME.getName(), producer.getName(), jsonSession.getString(ProducerField.NAME.getName()));
+         Assert.assertEquals(ProducerField.SESSION.getName(), producer.getSessionID(), jsonSession.getString(ProducerField.SESSION.getAlternativeName()));
+         Assert.assertEquals(ProducerField.ADDRESS.getName(), producer.getAddress(), jsonSession.getString(ProducerField.ADDRESS.getAlternativeName()));
+         Assert.assertEquals(ProducerField.MESSAGE_SENT.getName(), producer.getMessagesSent(), jsonSession.getJsonNumber(ProducerField.MESSAGE_SENT.getName()).longValue());
+         Assert.assertEquals(ProducerField.MESSAGE_SENT_SIZE.getName(), producer.getMessagesSentSize(), jsonSession.getJsonNumber(ProducerField.MESSAGE_SENT_SIZE.getName()).longValue());
+         Assert.assertEquals(ProducerField.CREATION_TIME.getName(), String.valueOf(producer.getCreationTime()), jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+      }
    }
 
    @Test
-   public void testListAddresses() throws Exception {
+   public void testListProducersAgainstServer() throws Exception {
       SimpleString queueName1 = new SimpleString("my_queue_one");
-      SimpleString queueName2 = new SimpleString("my_queue_two");
-      SimpleString queueName3 = new SimpleString("other_queue_three");
-      SimpleString queueName4 = new SimpleString("other_queue_four");
-
       SimpleString addressName1 = new SimpleString("my_address_one");
-      SimpleString addressName2 = new SimpleString("my_address_two");
-      SimpleString addressName3 = new SimpleString("other_address_three");
 
       ActiveMQServerControl serverControl = createManagementControl();
 
@@ -3413,392 +4749,624 @@ public class ActiveMQServerControlTest extends ManagementTestBase {
       } else {
          server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
-      server.addAddressInfo(new AddressInfo(addressName2, RoutingType.ANYCAST));
-      if (legacyCreateQueue) {
-         server.createQueue(addressName2, RoutingType.ANYCAST, queueName2, null, false, false);
-      } else {
-         server.createQueue(new QueueConfiguration(queueName2).setAddress(addressName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
-      }
-      server.addAddressInfo(new AddressInfo(addressName3, RoutingType.ANYCAST));
-      if (legacyCreateQueue) {
-         server.createQueue(addressName3, RoutingType.ANYCAST, queueName3, null, false, false);
-         server.createQueue(addressName3, RoutingType.ANYCAST, queueName4, null, false, false);
-      } else {
-         server.createQueue(new QueueConfiguration(queueName3).setAddress(addressName3).setRoutingType(RoutingType.ANYCAST).setDurable(false));
-         server.createQueue(new QueueConfiguration(queueName4).setAddress(addressName3).setRoutingType(RoutingType.ANYCAST).setDurable(false));
-      }
 
-      //test with CONTAINS filter
-      String filterString = createJsonFilter("name", "CONTAINS", "my_address");
-      String addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
-      JsonObject addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
-      JsonArray array = (JsonArray) addressesAsJsonObject.get("data");
+      // create some consumers
+      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator);) {
 
-      Assert.assertEquals("number of addresses returned from query", 2, array.size());
-      Assert.assertTrue("address name check", array.getJsonObject(0).getString("name").contains("my_address"));
-      Assert.assertTrue("address name check", array.getJsonObject(1).getString("name").contains("my_address"));
+         ClientSession session1 = csf.createSession();
 
-      //test with EQUALS filter
-      filterString = createJsonFilter("name", "EQUALS", addressName1.toString());
-      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
-      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
-      array = (JsonArray) addressesAsJsonObject.get("data");
+         ClientProducer producer1 = session1.createProducer(addressName1);
+         producer1.send(session1.createMessage(true));
 
-      Assert.assertEquals("number of addresses returned from query", 1, array.size());
-      //check all field names
-      Assert.assertEquals("address name check", addressName1.toString(), array.getJsonObject(0).getString("name"));
-      Assert.assertNotEquals("id", "", array.getJsonObject(0).getString("id"));
-      Assert.assertTrue("routingTypes", array.getJsonObject(0).getString("routingTypes").contains(RoutingType.ANYCAST.name()));
-      Assert.assertEquals("queueCount", "1", array.getJsonObject(0).getString("queueCount"));
+         //bring back all producers
+         String filterString = createJsonFilter("", "", "");
+         String producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         JsonArray array = (JsonArray) producersAsJsonObject.get("data");
 
-      //test with empty filter - all addresses should be returned
-      filterString = createJsonFilter("", "", "");
-      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
-      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
-      array = (JsonArray) addressesAsJsonObject.get("data");
+         Assert.assertEquals("number of producers returned from query", 1 + extraProducers, array.size());
 
-      Assert.assertTrue("number of addresses returned from query", 3 <= array.size());
+         JsonObject jsonSession = array.getJsonObject(0);
 
-      //test with small page size
-      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 1);
-      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
-      array = (JsonArray) addressesAsJsonObject.get("data");
+         //get the only server producer
+         ServerProducer producer = server.getSessionByID(jsonSession.getString(ProducerField.SESSION.getName())).getServerProducers().iterator().next();
+         //check all fields
+         Assert.assertEquals(ProducerField.ID.getName(), String.valueOf(producer.getID()), jsonSession.getString(ProducerField.ID.getName()));
+         Assert.assertEquals(ProducerField.SESSION.getName(), producer.getSessionID(), jsonSession.getString(ProducerField.SESSION.getName()));
+         Assert.assertEquals(ProducerField.PROTOCOL.getName(), producer.getProtocol(), jsonSession.getString(ProducerField.PROTOCOL.getName()));
+         Assert.assertEquals(ProducerField.ADDRESS.getName(), producer.getAddress(), jsonSession.getString(ProducerField.ADDRESS.getName()));
+         Assert.assertEquals(ProducerField.MESSAGE_SENT.getName(), producer.getMessagesSent(), jsonSession.getJsonNumber(ProducerField.MESSAGE_SENT.getName()).longValue());
+         Assert.assertEquals(ProducerField.MESSAGE_SENT_SIZE.getName(), producer.getMessagesSentSize(), jsonSession.getJsonNumber(ProducerField.MESSAGE_SENT_SIZE.getName()).longValue());
+         Assert.assertEquals(ProducerField.CREATION_TIME.getName(), String.valueOf(producer.getCreationTime()), jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+      }
+   }
+   @Test
+   public void testListProducersJMSCore() throws Exception {
+      testListProducersJMS(ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY)), "CORE");
+   }
 
-      Assert.assertEquals("number of queues returned from query", 1, array.size());
+   @Test
+   public void testListProducersJMSAMQP() throws Exception {
+      testListProducersJMS(new JmsConnectionFactory("amqp://localhost:61616"), "AMQP");
+   }
 
-      //test with QUEUE_COUNT with GREATER_THAN filter
-      filterString = createJsonFilter("QUEUE_COUNT", "GREATER_THAN", "1");
-      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
-      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
-      array = (JsonArray) addressesAsJsonObject.get("data");
+   @Test
+   public void testListProducersJMSOW() throws Exception {
+      testListProducersJMS(new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616"), "CORE");
+   }
 
-      Assert.assertEquals("number of addresses returned from query", 1, array.size());
-      Assert.assertEquals("address name check", addressName3.toString(), array.getJsonObject(0).getString("name"));
+   public void testListProducersJMS(ConnectionFactory connectionFactory, String protocol) throws Exception {
+      String queueName = "my_queue_one";
+      SimpleString ssQueueName = SimpleString.toSimpleString(queueName);
+      ActiveMQServerControl serverControl = createManagementControl();
 
-      //test with QUEUE_COUNT with LESS_THAN filter
-      filterString = createJsonFilter("QUEUE_COUNT", "LESS_THAN", "0");
-      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
-      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
-      array = (JsonArray) addressesAsJsonObject.get("data");
+      server.addAddressInfo(new AddressInfo(ssQueueName, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(ssQueueName, RoutingType.ANYCAST, ssQueueName, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName).setAddress(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+      // create some producers
+      try (Connection conn = connectionFactory.createConnection();) {
 
-      Assert.assertEquals("number of addresses returned from query", 0, array.size());
+         Session session1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         Session session2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
 
-   }
+         MessageProducer producer1 = session1.createProducer(session1.createQueue(queueName));
+         producer1.send(session1.createMessage());
+         MessageProducer producer2 = session2.createProducer(session2.createQueue(queueName));
+         producer2.send(session2.createMessage());
 
-   @Test
-   public void testListAddressOrder() throws Exception {
+         //bring back all producers
+         String filterString = createJsonFilter("", "", "");
+         String producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         JsonArray array = (JsonArray) producersAsJsonObject.get("data");
 
-      SimpleString queueName1 = new SimpleString("my_queue_one");
-      SimpleString queueName2 = new SimpleString("my_queue_two");
-      SimpleString queueName3 = new SimpleString("other_queue_three");
-      SimpleString queueName4 = new SimpleString("other_queue_four");
+         Assert.assertEquals("number of producers returned from query", 2 + extraProducers, array.size());
 
-      SimpleString addressName1 = new SimpleString("my_address_1");
-      SimpleString addressName2 = new SimpleString("my_address_2");
-      SimpleString addressName3 = new SimpleString("my_address_3");
+         boolean foundElement = false;
+         for (int i = 0; i < array.size(); i++) {
 
-      ActiveMQServerControl serverControl = createManagementControl();
+            JsonObject jsonSession = array.getJsonObject(i);
+            if (jsonSession.getString("address").equals("activemq.management")) {
+               continue;
+            }
 
-      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
-      if (legacyCreateQueue) {
-         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
-      } else {
-         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+            foundElement = true;
+
+            //check all fields
+            Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+            Assert.assertNotEquals(ProducerField.SESSION.getName(), "", jsonSession.getString(ProducerField.SESSION.getName()));
+            Assert.assertEquals(ProducerField.USER.getName(), "", jsonSession.getString(ProducerField.USER.getName()));
+            Assert.assertNotEquals(ProducerField.PROTOCOL.getName(), "", jsonSession.getString(ProducerField.PROTOCOL.getName()));
+            Assert.assertEquals(ProducerField.ADDRESS.getName(), queueName, jsonSession.getString(ProducerField.ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", jsonSession.getString(ProducerField.LOCAL_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", jsonSession.getString(ProducerField.REMOTE_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         }
+
+         Assert.assertTrue("Valid session not found", foundElement);
       }
-      server.addAddressInfo(new AddressInfo(addressName2, RoutingType.ANYCAST));
-      server.addAddressInfo(new AddressInfo(addressName3, RoutingType.ANYCAST));
+   }
+
+   @Test
+   public void testListProducersJMSLegacy() throws Exception {
+      String queueName = "my_queue_one";
+      SimpleString ssQueueName = SimpleString.toSimpleString(queueName);
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(ssQueueName, RoutingType.ANYCAST));
       if (legacyCreateQueue) {
-         server.createQueue(addressName3, RoutingType.ANYCAST, queueName3, null, false, false);
-         server.createQueue(addressName3, RoutingType.ANYCAST, queueName4, null, false, false);
+         server.createQueue(ssQueueName, RoutingType.ANYCAST, ssQueueName, null, false, false);
       } else {
-         server.createQueue(new QueueConfiguration(queueName3).setAddress(addressName3).setRoutingType(RoutingType.ANYCAST).setDurable(false));
-         server.createQueue(new QueueConfiguration(queueName4).setAddress(addressName3).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+         server.createQueue(new QueueConfiguration(queueName).setAddress(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
 
-      //test default order
-      String filterString = createJsonFilter("name", "CONTAINS", "my");
-      String addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
-      JsonObject addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
-      JsonArray array = (JsonArray) addressesAsJsonObject.get("data");
+      //pretend we are an olde client by removing the producer id and changing the session to use lagacy producers
+      server.getBrokerSessionPlugins().add(new ActiveMQServerSessionPlugin() {
+         @Override
+         public void beforeCreateSession(String name, String username, int minLargeMessageSize, RemotingConnection connection, boolean autoCommitSends, boolean autoCommitAcks, boolean preAcknowledge, boolean xa, String defaultAddress, SessionCallback callback, boolean autoCreateQueues, OperationContext context, Map<SimpleString, RoutingType> prefixes) throws ActiveMQException {
+            ActiveMQServerSessionPlugin.super.beforeCreateSession(name, username, minLargeMessageSize, connection, autoCommitSends, autoCommitAcks, preAcknowledge, xa, defaultAddress, callback, autoCreateQueues, context, prefixes);
+         }
 
-      Assert.assertEquals("number addresses returned", 3, array.size());
-      Assert.assertEquals("address1 default order", addressName1.toString(), array.getJsonObject(0).getString("name"));
-      Assert.assertEquals("address2 default order", addressName2.toString(), array.getJsonObject(1).getString("name"));
-      Assert.assertEquals("address3 default order", addressName3.toString(), array.getJsonObject(2).getString("name"));
+         @Override
+         public void afterCreateSession(ServerSession session) throws ActiveMQException {
+            try {
+               Field serverProducers = session.getClass().getDeclaredField("serverProducers");
+               serverProducers.setAccessible(true);
+               serverProducers.set(session, new ServerLegacyProducersImpl(session));
+            } catch (NoSuchFieldException e) {
+               throw new RuntimeException(e);
+            } catch (IllegalAccessException e) {
+               throw new RuntimeException(e);
+            }
+         }
+      });
+
+      ActiveMQConnectionFactory connectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));
+      // create some producers
+      try (Connection conn = connectionFactory.createConnection();) {
+
+         Session session1 = conn.createSession();
+         Session session2 = conn.createSession();
+
+         MessageProducer producer1 = session1.createProducer(session1.createQueue(queueName));
+         producer1.send(session1.createMessage());
+         MessageProducer producer2 = session2.createProducer(session2.createQueue(queueName));
+         producer2.send(session2.createMessage());
+
+         //bring back all producers
+         String filterString = createJsonFilter("", "", "");
+         String producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         JsonArray array = (JsonArray) producersAsJsonObject.get("data");
+
+         Assert.assertEquals("number of producers returned from query", 2, array.size());
+
+         boolean foundElement = false;
+         for (int i = 0; i < array.size(); i++) {
+
+            JsonObject jsonSession = array.getJsonObject(i);
+            if (jsonSession.getString("address").equals("activemq.management")) {
+               continue;
+            }
+
+            foundElement = true;
+
+            //check all fields
+            Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+            Assert.assertNotEquals(ProducerField.SESSION.getName(), "", jsonSession.getString(ProducerField.SESSION.getName()));
+            Assert.assertEquals(ProducerField.USER.getName(), "", jsonSession.getString(ProducerField.USER.getName()));
+            Assert.assertNotEquals(ProducerField.PROTOCOL.getName(), "", jsonSession.getString(ProducerField.PROTOCOL.getName()));
+            Assert.assertEquals(ProducerField.ADDRESS.getName(), queueName, jsonSession.getString(ProducerField.ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", jsonSession.getString(ProducerField.LOCAL_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", jsonSession.getString(ProducerField.REMOTE_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         }
+
+         Assert.assertTrue("Valid session not found", foundElement);
 
-      //test  ordered by name desc
-      filterString = createJsonFilter("name", "CONTAINS", "my", "name", "desc");
-      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
-      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
-      array = (JsonArray) addressesAsJsonObject.get("data");
+         session1.close();
 
-      Assert.assertEquals("number addresses returned", 3, array.size());
-      Assert.assertEquals("address3 ordered by name", addressName3.toString(), array.getJsonObject(0).getString("name"));
-      Assert.assertEquals("address2 ordered by name", addressName2.toString(), array.getJsonObject(1).getString("name"));
-      Assert.assertEquals("address1 ordered by name", addressName1.toString(), array.getJsonObject(2).getString("name"));
+         filterString = createJsonFilter("", "", "");
+         producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         array = (JsonArray) producersAsJsonObject.get("data");
 
-      //test  ordered by queue count asc
-      filterString = createJsonFilter("name", "CONTAINS", "my", "queueCount", "asc");
-      addressesAsJsonString = serverControl.listAddresses(filterString, 1, 50);
-      addressesAsJsonObject = JsonUtil.readJsonObject(addressesAsJsonString);
-      array = (JsonArray) addressesAsJsonObject.get("data");
+         Assert.assertEquals("number of producers returned from query", 1, array.size());
 
-      Assert.assertEquals("number addresses returned", 3, array.size());
-      Assert.assertEquals("address2 ordered by queue count", addressName2.toString(), array.getJsonObject(0).getString("name"));
-      Assert.assertEquals("address1 ordered by queue count", addressName1.toString(), array.getJsonObject(1).getString("name"));
-      Assert.assertEquals("address3 ordered by queue count", addressName3.toString(), array.getJsonObject(2).getString("name"));
+         session2.close();
+
+         filterString = createJsonFilter("", "", "");
+         producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         array = (JsonArray) producersAsJsonObject.get("data");
+
+         Assert.assertEquals("number of producers returned from query", 0, array.size());
+      }
    }
 
    @Test
-   public void testListConsumers() throws Exception {
+   public void testListFqqnProducersJMSLegacy() throws Exception {
       SimpleString queueName1 = new SimpleString("my_queue_one");
-      SimpleString queueName2 = new SimpleString("my_queue_two");
-      SimpleString queueName3 = new SimpleString("other_queue_three");
       SimpleString addressName1 = new SimpleString("my_address_one");
-      SimpleString addressName2 = new SimpleString("my_address_two");
-
+      SimpleString FQQNName = new SimpleString(addressName1 + "::" + queueName1);
       ActiveMQServerControl serverControl = createManagementControl();
 
-      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
+      server.addAddressInfo(new AddressInfo(FQQNName, RoutingType.ANYCAST));
       if (legacyCreateQueue) {
-         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
+         server.createQueue(FQQNName, RoutingType.ANYCAST, FQQNName, null, false, false);
       } else {
-         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+         server.createQueue(new QueueConfiguration(FQQNName).setAddress(FQQNName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
 
-      server.addAddressInfo(new AddressInfo(addressName2, RoutingType.ANYCAST));
+      //pretend we are an olde client by removing the producer id and changing the session to use lagacy producers
+      server.getBrokerSessionPlugins().add(new ActiveMQServerSessionPlugin() {
+         @Override
+         public void beforeCreateSession(String name, String username, int minLargeMessageSize, RemotingConnection connection, boolean autoCommitSends, boolean autoCommitAcks, boolean preAcknowledge, boolean xa, String defaultAddress, SessionCallback callback, boolean autoCreateQueues, OperationContext context, Map<SimpleString, RoutingType> prefixes) throws ActiveMQException {
+            ActiveMQServerSessionPlugin.super.beforeCreateSession(name, username, minLargeMessageSize, connection, autoCommitSends, autoCommitAcks, preAcknowledge, xa, defaultAddress, callback, autoCreateQueues, context, prefixes);
+         }
+
+         @Override
+         public void afterCreateSession(ServerSession session) throws ActiveMQException {
+            try {
+               Field serverProducers = session.getClass().getDeclaredField("serverProducers");
+               serverProducers.setAccessible(true);
+               serverProducers.set(session, new ServerLegacyProducersImpl(session));
+            } catch (NoSuchFieldException e) {
+               throw new RuntimeException(e);
+            } catch (IllegalAccessException e) {
+               throw new RuntimeException(e);
+            }
+         }
+      });
+      ActiveMQConnectionFactory connectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));
+      // create some producers
+      try (Connection conn = connectionFactory.createConnection();) {
+
+         Session session1 = conn.createSession();
+
+         MessageProducer producer1 = session1.createProducer(session1.createQueue(FQQNName.toString()));
+         producer1.send(session1.createMessage());
+
+         //bring back all producers
+         String filterString = createJsonFilter("", "", "");
+         String producersAsJsonString = serverControl.listProducers(filterString, 1, 200);
+         JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         JsonArray array = (JsonArray) producersAsJsonObject.get("data");
+
+         //this is testing that the producers tracked hasnt exceededd the max of 100
+         Assert.assertEquals("number of producers returned from query", 1, array.size());
+
+         boolean foundElement = false;
+         for (int i = 0; i < array.size(); i++) {
+
+            JsonObject jsonSession = array.getJsonObject(i);
+            if (jsonSession.getString("address").equals("activemq.management")) {
+               continue;
+            }
+
+            foundElement = true;
+
+            //check all fields
+            Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+            Assert.assertNotEquals(ProducerField.SESSION.getName(), "", jsonSession.getString(ProducerField.SESSION.getName()));
+            Assert.assertEquals(ProducerField.USER.getName(), "", jsonSession.getString(ProducerField.USER.getName()));
+            Assert.assertNotEquals(ProducerField.PROTOCOL.getName(), "", jsonSession.getString(ProducerField.PROTOCOL.getName()));
+            Assert.assertEquals(ProducerField.ADDRESS.getName(), FQQNName.toString(), jsonSession.getString(ProducerField.ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", jsonSession.getString(ProducerField.LOCAL_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", jsonSession.getString(ProducerField.REMOTE_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         }
+
+         Assert.assertTrue("Valid session not found", foundElement);
+      }
+   }
+
+   @Test
+   public void testListAnonProducersJMSLegacy() throws Exception {
+      String queueName = "my_queue_one";
+      SimpleString ssQueueName = SimpleString.toSimpleString(queueName);
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(ssQueueName, RoutingType.ANYCAST));
       if (legacyCreateQueue) {
-         server.createQueue(addressName2, RoutingType.ANYCAST, queueName2, null, false, false);
-         server.createQueue(addressName2, RoutingType.ANYCAST, queueName3, null, false, false);
+         server.createQueue(ssQueueName, RoutingType.ANYCAST, ssQueueName, null, false, false);
       } else {
-         server.createQueue(new QueueConfiguration(queueName2).setAddress(addressName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
-         server.createQueue(new QueueConfiguration(queueName3).setAddress(addressName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+         server.createQueue(new QueueConfiguration(queueName).setAddress(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
 
-      // create some consumers
-      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator); ClientSession session = csf.createSession()) {
+      //pretend we are an olde client by removing the producer id and changing the session to use lagacy producers
+      server.getBrokerSessionPlugins().add(new ActiveMQServerSessionPlugin() {
+         @Override
+         public void beforeCreateSession(String name, String username, int minLargeMessageSize, RemotingConnection connection, boolean autoCommitSends, boolean autoCommitAcks, boolean preAcknowledge, boolean xa, String defaultAddress, SessionCallback callback, boolean autoCreateQueues, OperationContext context, Map<SimpleString, RoutingType> prefixes) throws ActiveMQException {
+            ActiveMQServerSessionPlugin.super.beforeCreateSession(name, username, minLargeMessageSize, connection, autoCommitSends, autoCommitAcks, preAcknowledge, xa, defaultAddress, callback, autoCreateQueues, context, prefixes);
+         }
 
-         ClientConsumer consumer1_q1 = session.createConsumer(queueName1);
-         ClientConsumer consumer2_q1 = session.createConsumer(queueName1);
-         ClientConsumer consumer1_q2 = session.createConsumer(queueName2);
-         ClientConsumer consumer1_q3 = session.createConsumer(queueName3);
+         @Override
+         public void afterCreateSession(ServerSession session) throws ActiveMQException {
+            try {
+               Field serverProducers = session.getClass().getDeclaredField("serverProducers");
+               serverProducers.setAccessible(true);
+               serverProducers.set(session, new ServerLegacyProducersImpl(session));
+            } catch (NoSuchFieldException e) {
+               throw new RuntimeException(e);
+            } catch (IllegalAccessException e) {
+               throw new RuntimeException(e);
+            }
+         }
+      });
 
-         //test with filter  EQUALS
-         String filterString = createJsonFilter("queue", "EQUALS", queueName1.toString());
-         String consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
-         JsonObject consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
-         JsonArray array = (JsonArray) consumersAsJsonObject.get("data");
+      ActiveMQConnectionFactory connectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));
+      // create some producers
+      try (Connection conn = connectionFactory.createConnection();) {
 
-         Assert.assertEquals("number of consumers returned from query", 2, array.size());
-         Assert.assertEquals("check consumer's queue", queueName1.toString(), array.getJsonObject(0).getString("queue"));
-         Assert.assertEquals("check consumer's queue", queueName1.toString(), array.getJsonObject(0).getString("queue"));
+         Session session1 = conn.createSession();
 
-         // test with a CONTAINS operation
-         filterString = createJsonFilter("queue", "CONTAINS", "my_queue");
-         consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
-         consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
-         array = (JsonArray) consumersAsJsonObject.get("data");
+         MessageProducer producer1 = session1.createProducer(null);
+         for ( int i = 0; i < 110; i++) {
+            javax.jms.Queue queue = session1.createQueue(queueName + i);
+            producer1.send(queue, session1.createMessage());
+         }
 
-         Assert.assertEquals("number of consumers returned from query", 3, array.size());
+         //bring back all producers
+         String filterString = createJsonFilter("", "", "");
+         String producersAsJsonString = serverControl.listProducers(filterString, 1, 200);
+         JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         JsonArray array = (JsonArray) producersAsJsonObject.get("data");
 
-         // filter by address
-         filterString = createJsonFilter("address", "EQUALS", addressName1.toString());
-         consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
-         consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
-         array = (JsonArray) consumersAsJsonObject.get("data");
+         //this is testing that the producers tracked hasnt exceededd the max of 100
+         Assert.assertEquals("number of producers returned from query", 100, array.size());
 
-         Assert.assertEquals("number of consumers returned from query", 2, array.size());
-         Assert.assertEquals("check consumers address", addressName1.toString(), array.getJsonObject(0).getString("address"));
-         Assert.assertEquals("check consumers address", addressName1.toString(), array.getJsonObject(1).getString("address"));
+         boolean foundElement = false;
+         for (int i = 0; i < array.size(); i++) {
 
-         //test with empty filter - all consumers should be returned
-         filterString = createJsonFilter("", "", "");
-         consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
-         consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
-         array = (JsonArray) consumersAsJsonObject.get("data");
+            JsonObject jsonSession = array.getJsonObject(i);
+            if (jsonSession.getString("address").equals("activemq.management")) {
+               continue;
+            }
 
-         Assert.assertTrue("at least 4 consumers returned from query", 4 <= array.size());
+            foundElement = true;
 
-         //test with small page size
-         consumersAsJsonString = serverControl.listConsumers(filterString, 1, 1);
-         consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
-         array = (JsonArray) consumersAsJsonObject.get("data");
+            //check all fields
+            Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+            Assert.assertNotEquals(ProducerField.SESSION.getName(), "", jsonSession.getString(ProducerField.SESSION.getName()));
+            Assert.assertEquals(ProducerField.USER.getName(), "", jsonSession.getString(ProducerField.USER.getName()));
+            Assert.assertNotEquals(ProducerField.PROTOCOL.getName(), "", jsonSession.getString(ProducerField.PROTOCOL.getName()));
+            Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", jsonSession.getString(ProducerField.LOCAL_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", jsonSession.getString(ProducerField.REMOTE_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         }
 
-         Assert.assertEquals("number of consumers returned from query", 1, array.size());
+         Assert.assertTrue("Valid session not found", foundElement);
 
-         //test contents of returned consumer
-         filterString = createJsonFilter("queue", "EQUALS", queueName3.toString());
-         consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
-         consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
-         array = (JsonArray) consumersAsJsonObject.get("data");
+         session1.close();
 
-         Assert.assertEquals("number of consumers returned from query", 1, array.size());
-         JsonObject jsonConsumer = array.getJsonObject(0);
-         Assert.assertEquals("queue name in consumer", queueName3.toString(), jsonConsumer.getString("queue"));
-         Assert.assertEquals("address name in consumer", addressName2.toString(), jsonConsumer.getString("address"));
-         Assert.assertEquals("consumer protocol ", "CORE", jsonConsumer.getString("protocol"));
-         Assert.assertEquals("queue type", "anycast", jsonConsumer.getString("queueType"));
-         Assert.assertNotEquals("id", "", jsonConsumer.getString("id"));
-         Assert.assertNotEquals("session", "", jsonConsumer.getString("session"));
-         Assert.assertEquals("clientID", "", jsonConsumer.getString("clientID"));
-         Assert.assertEquals("user", "", jsonConsumer.getString("user"));
-         Assert.assertNotEquals("localAddress", "", jsonConsumer.getString("localAddress"));
-         Assert.assertNotEquals("remoteAddress", "", jsonConsumer.getString("remoteAddress"));
-         Assert.assertNotEquals("creationTime", "", jsonConsumer.getString("creationTime"));
+         filterString = createJsonFilter("", "", "");
+         producersAsJsonString = serverControl.listProducers(filterString, 1, 110);
+         producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         array = (JsonArray) producersAsJsonObject.get("data");
+
+         Assert.assertEquals("number of producers returned from query", 0, array.size());
       }
+   }
 
+   @Test
+   public void testListProducersJMSCoreMultipleProducers() throws Exception {
+      testListProducersJMSMultipleProducers(ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY)), "CORE");
    }
 
    @Test
-   public void testListConsumersOrder() throws Exception {
-      SimpleString queueName1 = new SimpleString("my_queue_one");
-      SimpleString addressName1 = new SimpleString("my_address_one");
+   public void testListProducersJMSAMQPMultipleProducers() throws Exception {
+      testListProducersJMSMultipleProducers(new JmsConnectionFactory("amqp://localhost:61616"), "AMQP");
+   }
 
+   @Test
+   public void testListProducersJMSOpenWireMultipleProducers() throws Exception {
+      testListProducersJMSMultipleProducers(new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616"), "OPENWIRE");
+   }
+   public void testListProducersJMSMultipleProducers(ConnectionFactory connectionFactory, String protocol) throws Exception {
+      String queueName = "my_queue_one";
+      SimpleString ssQueueName = SimpleString.toSimpleString(queueName);
       ActiveMQServerControl serverControl = createManagementControl();
 
-      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
+      server.addAddressInfo(new AddressInfo(ssQueueName, RoutingType.ANYCAST));
       if (legacyCreateQueue) {
-         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
+         server.createQueue(ssQueueName, RoutingType.ANYCAST, ssQueueName, null, false, false);
       } else {
-         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+         server.createQueue(new QueueConfiguration(queueName).setAddress(queueName).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
+      // create some producers
+      try (Connection conn = connectionFactory.createConnection();) {
 
-      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator);) {
+         Session session1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
 
-         ClientSessionImpl session1 = (ClientSessionImpl) csf.createSession();
-         ClientSessionImpl session2 = (ClientSessionImpl) csf.createSession();
-         ClientSessionImpl session3 = (ClientSessionImpl) csf.createSession();
+         MessageProducer producer1 = session1.createProducer(session1.createQueue(queueName));
+         producer1.send(session1.createMessage());
 
-         //sleep - test compares creationTimes
-         ClientConsumer consumer_s1 = session1.createConsumer(queueName1);
-         Thread.sleep(500);
-         ClientConsumer consumer_s2 = session2.createConsumer(queueName1);
-         Thread.sleep(500);
-         ClientConsumer consumer_s3 = session3.createConsumer(queueName1);
+         //bring back all producers
+         String filterString = createJsonFilter("", "", "");
+         String producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         JsonArray array = (JsonArray) producersAsJsonObject.get("data");
 
-         //test default Order
-         String filterString = createJsonFilter("queue", "EQUALS", queueName1.toString());
-         String consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
-         JsonObject consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
-         JsonArray array = (JsonArray) consumersAsJsonObject.get("data");
-         Assert.assertEquals("number of consumers returned from query", 3, array.size());
+         Assert.assertEquals("number of producers returned from query", 1 + extraProducers, array.size());
 
-         Assert.assertEquals("Consumer1 default order", session1.getName(), array.getJsonObject(0).getString("session"));
-         Assert.assertEquals("Consumer2 default order", session2.getName(), array.getJsonObject(1).getString("session"));
-         Assert.assertEquals("Consumer3 default order", session3.getName(), array.getJsonObject(2).getString("session"));
+         boolean foundElement = false;
+         for (int i = 0; i < array.size(); i++) {
 
-         //test ordered by creationTime
-         filterString = createJsonFilter("queue", "EQUALS", queueName1.toString(), "creationTime", "desc");
-         consumersAsJsonString = serverControl.listConsumers(filterString, 1, 50);
-         consumersAsJsonObject = JsonUtil.readJsonObject(consumersAsJsonString);
-         array = (JsonArray) consumersAsJsonObject.get("data");
-         Assert.assertEquals("number of consumers returned from query", 3, array.size());
+            JsonObject jsonSession = array.getJsonObject(i);
+            if (jsonSession.getString("address").equals("activemq.management")) {
+               continue;
+            }
+
+            foundElement = true;
+
+            //check all fields
+            Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+            Assert.assertNotEquals(ProducerField.SESSION.getName(), "", jsonSession.getString(ProducerField.SESSION.getName()));
+            Assert.assertEquals(ProducerField.USER.getName(), "", jsonSession.getString(ProducerField.USER.getName()));
+            Assert.assertNotEquals(ProducerField.PROTOCOL.getName(), "", jsonSession.getString(ProducerField.PROTOCOL.getName()));
+            Assert.assertEquals(ProducerField.ADDRESS.getName(), queueName, jsonSession.getString(ProducerField.ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", jsonSession.getString(ProducerField.LOCAL_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", jsonSession.getString(ProducerField.REMOTE_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         }
+
+         MessageProducer producer2 = session1.createProducer(session1.createQueue(queueName));
+         producer2.send(session1.createMessage());
+
+         producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         array = (JsonArray) producersAsJsonObject.get("data");
 
-         Assert.assertEquals("Consumer3 creation time", session3.getName(), array.getJsonObject(0).getString("session"));
-         Assert.assertEquals("Consumer2 creation time", session2.getName(), array.getJsonObject(1).getString("session"));
-         Assert.assertEquals("Consumer1 creation time", session1.getName(), array.getJsonObject(2).getString("session"));
+         Assert.assertEquals("number of producers returned from query", 2 + extraProducers, array.size());
 
+         producer1.close();
+
+         Wait.assertEquals(1 + extraProducers, () -> ((JsonArray) JsonUtil.readJsonObject(serverControl.listProducers(filterString, 1, 50)).get("data")).size());
+
+         producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         array = (JsonArray) producersAsJsonObject.get("data");
+
+         Assert.assertEquals("number of producers returned from query", 1 + extraProducers, array.size());
+
+         Assert.assertTrue("Valid session not found", foundElement);
       }
    }
 
    @Test
-   public void testListSessions() throws Exception {
-      SimpleString queueName1 = new SimpleString("my_queue_one");
-      SimpleString addressName1 = new SimpleString("my_address_one");
+   public void testListProducersJMSAnonCore() throws Exception {
+      testListProducersJMSAnon(ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY)), "CORE");
+   }
+
+   @Test
+   public void testListProducersJMSAnonAMQP() throws Exception {
+      testListProducersJMSAnon(new JmsConnectionFactory("amqp://localhost:61616"), "AMQP");
+   }
 
+   @Test
+   public void testListProducersJMSAnonOW() throws Exception {
+      testListProducersJMSAnon(new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616"), "OPENWIRE");
+   }
+
+   public void testListProducersJMSAnon(ConnectionFactory connectionFactory, String protocol) throws Exception {
+      String queueName1 = "my_queue_one";
+      String queueName2 = "my_queue_two";
+      String queueName3 = "my_queue_three";
+      SimpleString ssQueueName1 = SimpleString.toSimpleString(queueName1);
+      SimpleString ssQueueName2 = SimpleString.toSimpleString(queueName2);
+      SimpleString ssQueueName3 = SimpleString.toSimpleString(queueName3);
       ActiveMQServerControl serverControl = createManagementControl();
 
-      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
+      server.addAddressInfo(new AddressInfo(ssQueueName1, RoutingType.ANYCAST));
+      server.addAddressInfo(new AddressInfo(ssQueueName2, RoutingType.ANYCAST));
+      server.addAddressInfo(new AddressInfo(ssQueueName3, RoutingType.ANYCAST));
       if (legacyCreateQueue) {
-         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
+         server.createQueue(ssQueueName1, RoutingType.ANYCAST, ssQueueName1, null, false, false);
+         server.createQueue(ssQueueName2, RoutingType.ANYCAST, ssQueueName2, null, false, false);
+         server.createQueue(ssQueueName3, RoutingType.ANYCAST, ssQueueName3, null, false, false);
       } else {
-         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+         server.createQueue(new QueueConfiguration(queueName1).setAddress(queueName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+         server.createQueue(new QueueConfiguration(queueName2).setAddress(queueName2).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+         server.createQueue(new QueueConfiguration(queueName3).setAddress(queueName3).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
+      // create some producers
+      try (Connection conn = connectionFactory.createConnection();) {
+
+         Session session1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         Session session2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         javax.jms.Queue queue1 = session1.createQueue(queueName1);
+         javax.jms.Queue queue2 = session1.createQueue(queueName2);
+         javax.jms.Queue queue3 = session1.createQueue(queueName3);
+         MessageProducer producer1 = session1.createProducer(null);
+         producer1.send(queue1, session1.createMessage());
+         producer1.send(queue2, session1.createMessage());
+         producer1.send(queue3, session1.createMessage());
+         MessageProducer producer2 = session2.createProducer(null);
+         producer2.send(queue1, session2.createMessage());
+         producer2.send(queue2, session2.createMessage());
+         producer2.send(queue3, session2.createMessage());
 
-      // create some consumers
-      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator);) {
+         //bring back all producers
+         String filterString = createJsonFilter("", "", "");
+         String producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         JsonArray array = (JsonArray) producersAsJsonObject.get("data");
 
-         ClientSessionImpl session1 = (ClientSessionImpl) csf.createSession();
-         Thread.sleep(500);
-         ClientSessionImpl session2 = (ClientSessionImpl) csf.createSession();
-         Thread.sleep(500);
-         ClientSessionImpl session3 = (ClientSessionImpl) csf.createSession();
-         ClientConsumer consumer1_s1 = session1.createConsumer(queueName1);
-         ClientConsumer consumer2_s1 = session1.createConsumer(queueName1);
+         Assert.assertEquals("number of producers returned from query", 2 + extraProducers, array.size());
 
-         ClientConsumer consumer1_s2 = session2.createConsumer(queueName1);
-         ClientConsumer consumer2_s2 = session2.createConsumer(queueName1);
-         ClientConsumer consumer3_s2 = session2.createConsumer(queueName1);
-         ClientConsumer consumer4_s2 = session2.createConsumer(queueName1);
+         boolean foundElement = false;
+         for (int i = 0; i < array.size(); i++) {
 
-         ClientConsumer consumer1_s3 = session3.createConsumer(queueName1);
-         ClientConsumer consumer2_s3 = session3.createConsumer(queueName1);
-         ClientConsumer consumer3_s3 = session3.createConsumer(queueName1);
+            JsonObject jsonSession = array.getJsonObject(i);
+            if (jsonSession.getString("address").equals("activemq.management")) {
+               continue;
+            }
 
-         String filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "1");
-         String sessionsAsJsonString = serverControl.listSessions(filterString, 1, 50);
-         JsonObject sessionsAsJsonObject = JsonUtil.readJsonObject(sessionsAsJsonString);
-         JsonArray array = (JsonArray) sessionsAsJsonObject.get("data");
+            foundElement = true;
 
+            //check all fields
+            Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+            Assert.assertNotEquals(ProducerField.SESSION.getName(), "", jsonSession.getString(ProducerField.SESSION.getName()));
+            Assert.assertEquals(ProducerField.USER.getName(), "", jsonSession.getString(ProducerField.USER.getName()));
+            Assert.assertNotEquals(ProducerField.PROTOCOL.getName(), "", jsonSession.getString(ProducerField.PROTOCOL.getName()));
+            Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", jsonSession.getString(ProducerField.LOCAL_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", jsonSession.getString(ProducerField.REMOTE_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         }
 
-         Assert.assertEquals("number of sessions returned from query", 3, array.size());
-         JsonObject jsonSession = array.getJsonObject(0);
+         Assert.assertTrue("Valid session not found", foundElement);
+      }
+   }
 
-         //check all fields
-         Assert.assertNotEquals("id", "", jsonSession.getString("id"));
-         Assert.assertEquals("user", "", jsonSession.getString("user"));
-         Assert.assertNotEquals("creationTime", "", jsonSession.getString("creationTime"));
-         Assert.assertEquals("consumerCount", 2, jsonSession.getInt("consumerCount"));
-         Assert.assertTrue("producerCount", 0 <= jsonSession.getInt("producerCount"));
-         Assert.assertNotEquals("connectionID", "", jsonSession.getString("connectionID"));
+   @Test
+   public void testListProducersJMSTopicCore() throws Exception {
+      testListProducersJMSTopic(ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY)), "CORE");
+   }
+
+   @Test
+   public void testListProducersJMSTopicAMQP() throws Exception {
+      testListProducersJMSTopic(new JmsConnectionFactory("amqp://localhost:61616"), "AMQP");
+   }
+
+   @Test
+   public void testListProducersJMSTopicOW() throws Exception {
+      testListProducersJMSTopic(new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616"), "OPENWIRE");
+   }
+   public void testListProducersJMSTopic(ConnectionFactory connectionFactory, String protocol) throws Exception {
+      SimpleString topicName = SimpleString.toSimpleString("my-topic");
+      ActiveMQServerControl serverControl = createManagementControl();
 
-         //check default order
-         Assert.assertEquals("session1 location", session1.getName(), array.getJsonObject(0).getString("id"));
-         Assert.assertEquals("session2 location", session2.getName(), array.getJsonObject(1).getString("id"));
-         Assert.assertEquals("session3 location", session3.getName(), array.getJsonObject(2).getString("id"));
+      server.addAddressInfo(new AddressInfo(topicName, RoutingType.MULTICAST));
+      if (legacyCreateQueue) {
+         return;
+      }
 
-         //bring back session ordered by consumer count
-         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "1", "consumerCount", "asc");
-         sessionsAsJsonString = serverControl.listSessions(filterString, 1, 50);
-         sessionsAsJsonObject = JsonUtil.readJsonObject(sessionsAsJsonString);
-         array = (JsonArray) sessionsAsJsonObject.get("data");
+      server.addAddressInfo(new AddressInfo(""));
 
-         Assert.assertTrue("number of sessions returned from query", 3 == array.size());
-         Assert.assertEquals("session1 ordered by consumer", session1.getName(), array.getJsonObject(0).getString("id"));
-         Assert.assertEquals("session3 ordered by consumer", session3.getName(), array.getJsonObject(1).getString("id"));
-         Assert.assertEquals("session2 ordered by consumer", session2.getName(), array.getJsonObject(2).getString("id"));
+      try (Connection conn = connectionFactory.createConnection();) {
+         conn.setClientID("clientID");
+         Session session1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         Session session2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
 
-         //bring back session ordered by consumer Count
-         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "1", "consumerCount", "asc");
-         sessionsAsJsonString = serverControl.listSessions(filterString, 1, 50);
-         sessionsAsJsonObject = JsonUtil.readJsonObject(sessionsAsJsonString);
-         array = (JsonArray) sessionsAsJsonObject.get("data");
+         Topic topic = session1.createTopic(topicName.toString());
+         TopicSubscriber mysub1 = session1.createDurableSubscriber(topic, "mysub1");
+         TopicSubscriber mysub2 = session2.createDurableSubscriber(topic, "mysub2");
+         MessageProducer producer1 = session1.createProducer(topic);
+         producer1.send(session1.createMessage());
+         MessageProducer producer2 = session2.createProducer(session2.createTopic(topicName.toString()));
+         producer2.send(session2.createMessage());
 
-         Assert.assertTrue("number of sessions returned from query", 3 == array.size());
-         Assert.assertEquals("session1 ordered by consumer", session1.getName(), array.getJsonObject(0).getString("id"));
-         Assert.assertEquals("session3 ordered by consumer", session3.getName(), array.getJsonObject(1).getString("id"));
-         Assert.assertEquals("session2 ordered by consumer", session2.getName(), array.getJsonObject(2).getString("id"));
+         //bring back all producers
+         String filterString = createJsonFilter("", "", "");
+         String producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         JsonArray array = (JsonArray) producersAsJsonObject.get("data");
 
-         //bring back session ordered by creation time (desc)
-         filterString = createJsonFilter("CONSUMER_COUNT", "GREATER_THAN", "1", "creationTime", "desc");
-         sessionsAsJsonString = serverControl.listSessions(filterString, 1, 50);
-         sessionsAsJsonObject = JsonUtil.readJsonObject(sessionsAsJsonString);
-         array = (JsonArray) sessionsAsJsonObject.get("data");
+         Assert.assertEquals("number of producers returned from query", 2 + extraProducers, array.size());
 
-         Assert.assertTrue("number of sessions returned from query", 3 == array.size());
-         Assert.assertEquals("session3 ordered by creationTime", session3.getName(), array.getJsonObject(0).getString("id"));
-         Assert.assertEquals("session2 ordered by creationTime", session2.getName(), array.getJsonObject(1).getString("id"));
-         Assert.assertEquals("session1 ordered by creationTime", session1.getName(), array.getJsonObject(2).getString("id"));
+         boolean foundElement = false;
+         for (int i = 0; i < array.size(); i++) {
+
+            JsonObject jsonSession = array.getJsonObject(i);
+            if (jsonSession.getString("address").equals("activemq.management")) {
+               continue;
+            }
+
+            foundElement = true;
 
+            //check all fields
+            Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+            Assert.assertNotEquals(ProducerField.SESSION.getName(), "", jsonSession.getString(ProducerField.SESSION.getName()));
+            Assert.assertEquals(ProducerField.USER.getName(), "", jsonSession.getString(ProducerField.USER.getName()));
+            Assert.assertNotEquals(ProducerField.PROTOCOL.getName(), "", jsonSession.getString(ProducerField.PROTOCOL.getName()));
+            Assert.assertEquals(ProducerField.ADDRESS.getName(), topicName.toString(), jsonSession.getString(ProducerField.ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", jsonSession.getString(ProducerField.LOCAL_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", jsonSession.getString(ProducerField.REMOTE_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         }
+
+         //remove the subs and make sure producers still exist
+         mysub1.close();
+         mysub2.close();
+         session1.unsubscribe("mysub1");
+         session2.unsubscribe("mysub2");
+         producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         array = (JsonArray) producersAsJsonObject.get("data");
+         assertEquals(2 + extraProducers, array.size());
+         Assert.assertTrue("Valid session not found", foundElement);
       }
    }
 
-   @RetryMethod(retries = 2) // the list of connections eventually comes from a hashmap on a different order. Which is fine but makes the test fail. a Retry is ok
    @Test
-   public void testListConnections() throws Exception {
+   public void testListProducersFQQN() throws Exception {
       SimpleString queueName1 = new SimpleString("my_queue_one");
       SimpleString addressName1 = new SimpleString("my_address_one");
-
+      SimpleString FQQNName = new SimpleString(addressName1 + "::" + queueName1);
       ActiveMQServerControl serverControl = createManagementControl();
 
       server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
@@ -3808,117 +5376,79 @@ public class ActiveMQServerControlTest extends ManagementTestBase {
          server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
 
-      ClientSessionFactoryImpl csf = null;
-      ClientSessionFactoryImpl csf2 = null;
-      ClientSessionFactoryImpl csf3 = null;
-
       // create some consumers
-      try (ServerLocator locator = createInVMNonHALocator()) {
-
-         //sleep as test compares creationTime
-         csf = (ClientSessionFactoryImpl) createSessionFactory(locator);
-         Thread.sleep(50);
-         csf2 = (ClientSessionFactoryImpl) createSessionFactory(locator);
-         Thread.sleep(50);
-         csf3 = (ClientSessionFactoryImpl) createSessionFactory(locator);
-
-         ClientSession session1_c1 = csf.createSession("guest", "guest", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
-         ClientSession session2_c1 = csf.createSession("guest", "guest", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
+      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator);) {
 
-         ClientSession session1_c2 = csf2.createSession("myUser", "myPass", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
-         ClientSession session2_c2 = csf2.createSession("myUser", "myPass", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
-         ClientSession session3_c2 = csf2.createSession("myUser", "myPass", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
-         ClientSession session4_c2 = csf2.createSession("myUser", "myPass", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
+         ClientSession session1 = csf.createSession();
+         ClientSession session2 = csf.createSession();
 
-         ClientSession session1_c4 = csf3.createSession("myUser", "myPass", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
-         ClientSession session2_c4 = csf3.createSession("guest", "guest", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
-         ClientSession session3_c4 = csf3.createSession("guest", "guest", false, true, true, locator.isPreAcknowledge(), locator.getAckBatchSize());
+         ClientProducer producer1 = session1.createProducer(FQQNName);
+         producer1.send(session1.createMessage(true));
+         ClientProducer producer2 = session2.createProducer(FQQNName);
+         producer2.send(session2.createMessage(true));
 
-         String filterString = createJsonFilter("SESSION_COUNT", "GREATER_THAN", "1");
-         String connectionsAsJsonString = serverControl.listConnections(filterString, 1, 50);
-         System.err.println(connectionsAsJsonString);
-         JsonObject connectionsAsJsonObject = JsonUtil.readJsonObject(connectionsAsJsonString);
-         JsonArray array = (JsonArray) connectionsAsJsonObject.get("data");
+         //bring back all producers
+         String filterString = createJsonFilter("", "", "");
+         String producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         JsonArray array = (JsonArray) producersAsJsonObject.get("data");
 
-         Assert.assertEquals("number of connections returned from query", 3, array.size());
-         JsonObject jsonConnection = array.getJsonObject(0);
+         Assert.assertEquals("number of producers returned from query", 2 + extraProducers, array.size());
 
-         //check all fields
-         Assert.assertNotEquals("connectionID", "", jsonConnection.getString("connectionID"));
-         Assert.assertNotEquals("remoteAddress", "", jsonConnection.getString("remoteAddress"));
-         Assert.assertEquals("users", "guest", jsonConnection.getString("users"));
-         Assert.assertNotEquals("creationTime", "", jsonConnection.getString("creationTime"));
-         Assert.assertNotEquals("implementation", "", jsonConnection.getString("implementation"));
-         Assert.assertNotEquals("protocol", "", jsonConnection.getString("protocol"));
-         Assert.assertEquals("clientID", "", jsonConnection.getString("clientID"));
-         Assert.assertNotEquals("localAddress", "", jsonConnection.getString("localAddress"));
-         Assert.assertEquals("sessionCount", 2, jsonConnection.getInt("sessionCount"));
+         boolean foundElement = false;
+         for (int i = 0; i < array.size(); i++) {
 
-         //check default order
-         Assert.assertEquals("connection1 default Order", csf.getConnection().getID(), array.getJsonObject(0).getString("connectionID"));
-         Assert.assertEquals("connection2 default Order", csf2.getConnection().getID(), array.getJsonObject(1).getString("connectionID"));
-         Assert.assertEquals("connection3 session Order", csf3.getConnection().getID(), array.getJsonObject(2).getString("connectionID"));
+            JsonObject jsonSession = array.getJsonObject(i);
+            if (jsonSession.getString("address").equals("activemq.management")) {
+               continue;
+            }
 
-         //check order by users asc
-         filterString = createJsonFilter("SESSION_COUNT", "GREATER_THAN", "1", "users", "asc");
-         connectionsAsJsonString = serverControl.listConnections(filterString, 1, 50);
-         connectionsAsJsonObject = JsonUtil.readJsonObject(connectionsAsJsonString);
-         array = (JsonArray) connectionsAsJsonObject.get("data");
+            foundElement = true;
 
-         Assert.assertEquals("number of connections returned from query", 3, array.size());
-         Assert.assertEquals("connection1 users Order", "guest", array.getJsonObject(0).getString("users"));
-         Assert.assertEquals("connection3 users Order", "guest,myUser", array.getJsonObject(1).getString("users"));
-         Assert.assertEquals("connection2 users Order", "myUser", array.getJsonObject(2).getString("users"));
+            //check all fields
+            Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+            Assert.assertNotEquals(ProducerField.SESSION.getName(), "", jsonSession.getString(ProducerField.SESSION.getName()));
+            Assert.assertEquals(ProducerField.USER.getName(), "", jsonSession.getString(ProducerField.USER.getName()));
+            Assert.assertNotEquals(ProducerField.PROTOCOL.getName(), "", jsonSession.getString(ProducerField.PROTOCOL.getName()));
+            Assert.assertEquals(ProducerField.ADDRESS.getName(), FQQNName.toString(), jsonSession.getString(ProducerField.ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", jsonSession.getString(ProducerField.LOCAL_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", jsonSession.getString(ProducerField.REMOTE_ADDRESS.getName()));
+            Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         }
 
-         //check order by users desc
-         filterString = createJsonFilter("SESSION_COUNT", "GREATER_THAN", "1", "users", "desc");
-         connectionsAsJsonString = serverControl.listConnections(filterString, 1, 50);
-         connectionsAsJsonObject = JsonUtil.readJsonObject(connectionsAsJsonString);
-         array = (JsonArray) connectionsAsJsonObject.get("data");
+         session1.deleteQueue(queueName1);
 
-         Assert.assertEquals("number of connections returned from query", 3, array.size());
-         Assert.assertEquals("connection2 users Order", "myUser", array.getJsonObject(0).getString("users"));
-         Assert.assertEquals("connection3 users Order", "guest,myUser", array.getJsonObject(1).getString("users"));
-         Assert.assertEquals("connection1 users Order", "guest", array.getJsonObject(2).getString("users"));
+         producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         array = (JsonArray) producersAsJsonObject.get("data");
 
-         //check order by session count desc
-         filterString = createJsonFilter("SESSION_COUNT", "GREATER_THAN", "1", "sessionCount", "desc");
-         connectionsAsJsonString = serverControl.listConnections(filterString, 1, 50);
-         connectionsAsJsonObject = JsonUtil.readJsonObject(connectionsAsJsonString);
-         array = (JsonArray) connectionsAsJsonObject.get("data");
+         //make sure both producers still exist as we dont tie them to an address which would only be recreated on another send
+         assertEquals(2 + extraProducers, array.size());
 
-         Assert.assertEquals("number of connections returned from query", 3, array.size());
-         Assert.assertEquals("connection2 session Order", csf2.getConnection().getID(), array.getJsonObject(0).getString("connectionID"));
-         Assert.assertEquals("connection3 session Order", csf3.getConnection().getID(), array.getJsonObject(1).getString("connectionID"));
-         Assert.assertEquals("connection1 session Order", csf.getConnection().getID(), array.getJsonObject(2).getString("connectionID"));
+         Assert.assertTrue("Valid session not found", foundElement);
+      }
+   }
 
-         //check order by creationTime desc
-         filterString = createJsonFilter("SESSION_COUNT", "GREATER_THAN", "1", "creationTime", "desc");
-         connectionsAsJsonString = serverControl.listConnections(filterString, 1, 50);
-         connectionsAsJsonObject = JsonUtil.readJsonObject(connectionsAsJsonString);
-         array = (JsonArray) connectionsAsJsonObject.get("data");
+   @Test
+   public void testListProducersMessageCountsJMSCore() throws Exception {
+      testListProducersMessageCountsJMS(ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY)), "CORE");
+   }
 
-         Assert.assertEquals("number of connections returned from query", 3, array.size());
-         Assert.assertEquals("connection3 creationTime Order", csf3.getConnection().getID(), array.getJsonObject(0).getString("connectionID"));
-         Assert.assertEquals("connection2 creationTime Order", csf2.getConnection().getID(), array.getJsonObject(1).getString("connectionID"));
-         Assert.assertEquals("connection1 creationTime Order", csf.getConnection().getID(), array.getJsonObject(2).getString("connectionID"));
-      } finally {
-         if (csf != null) {
-            csf.close();
-         }
-         if (csf2 != null) {
-            csf.close();
-         }
-         if (csf3 != null) {
-            csf.close();
-         }
-      }
+   @Test
+   public void testListProducersMessageCountsAMQPJMS() throws Exception {
+      testListProducersMessageCountsJMS(new JmsConnectionFactory("amqp://localhost:61616"), "AMQP");
    }
 
    @Test
-   public void testListConnectionsClientID() throws Exception {
-      SimpleString queueName1 = new SimpleString("my_queue_one");
-      SimpleString addressName1 = new SimpleString("my_address_one");
+   public void testListProducersMessageCountsOWJMS() throws Exception {
+      testListProducersMessageCountsJMS(new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616"), "OPENWIRE");
+   }
+
+   public void testListProducersMessageCountsJMS(ConnectionFactory connectionFactory, String protocol) throws Exception {
+      String myQueue = "my_queue";
+      SimpleString queueName1 = new SimpleString(myQueue);
+      SimpleString addressName1 = new SimpleString(myQueue);
+
 
       ActiveMQServerControl serverControl = createManagementControl();
 
@@ -3929,36 +5459,42 @@ public class ActiveMQServerControlTest extends ManagementTestBase {
          server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
 
-      ClientSessionFactoryImpl csf = null;
+      int numMessages = 10;
 
-      // create some consumers
-      try (ServerLocator locator = createInVMNonHALocator()) {
-         //sleep as test compares creationTime
-         csf = (ClientSessionFactoryImpl) createSessionFactory(locator);
-         ClientSession session1_c1 = csf.createSession();
-         ClientSession session2_c1 = csf.createSession();
-         session1_c1.addMetaData(ClientSession.JMS_SESSION_IDENTIFIER_PROPERTY, "");
-         session1_c1.addMetaData(ClientSession.JMS_SESSION_CLIENT_ID_PROPERTY, "MYClientID");
+      try (Connection connection = connectionFactory.createConnection();) {
+         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         MessageProducer producer = session.createProducer(session.createQueue(myQueue));
+         for (int i = 0; i < numMessages; i++) {
+            javax.jms.Message message = session.createMessage();
+            producer.send(message);
+         }
+         //bring back all producers
+         String filterString = createJsonFilter("", "", "");
+         String producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
+         JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+         JsonArray array = (JsonArray) producersAsJsonObject.get("data");
 
-         String filterString = createJsonFilter("SESSION_COUNT", "GREATER_THAN", "1");
-         String connectionsAsJsonString = serverControl.listConnections(filterString, 1, 50);
-         JsonObject connectionsAsJsonObject = JsonUtil.readJsonObject(connectionsAsJsonString);
-         JsonArray array = (JsonArray) connectionsAsJsonObject.get("data");
+         Assert.assertEquals("number of producers returned from query", 1 + extraProducers, array.size());
 
-         Assert.assertEquals("number of connections returned from query", 1, array.size());
-         JsonObject jsonConnection = array.getJsonObject(0);
+         JsonObject jsonSession = array.getJsonObject(0);
 
          //check all fields
-         Assert.assertEquals("clientID", "MYClientID", jsonConnection.getString("clientID"));
-      } finally {
-         if (csf != null) {
-            csf.close();
-         }
+         Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+         Assert.assertNotEquals(ProducerField.SESSION.getName(), "", jsonSession.getString(ProducerField.SESSION.getName()));
+         Assert.assertEquals(ProducerField.USER.getName(), "", jsonSession.getString(ProducerField.USER.getName()));
+         Assert.assertEquals(ProducerField.PROTOCOL.getAlternativeName(), protocol, jsonSession.getString(ProducerField.PROTOCOL.getName()));
+         Assert.assertEquals(ProducerField.ADDRESS.getName(), addressName1.toString(), jsonSession.getString(ProducerField.ADDRESS.getName()));
+         Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", jsonSession.getString(ProducerField.LOCAL_ADDRESS.getName()));
+         Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", jsonSession.getString(ProducerField.REMOTE_ADDRESS.getName()));
+         Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         Assert.assertEquals(ProducerField.MESSAGE_SENT.getName(), numMessages, jsonSession.getInt(ProducerField.MESSAGE_SENT.getName()));
+         Assert.assertNotEquals(ProducerField.LAST_PRODUCED_MESSAGE_ID.getName(), "", jsonSession.getString(ProducerField.LAST_PRODUCED_MESSAGE_ID.getName()));
       }
    }
 
+
    @Test
-   public void testListProducers() throws Exception {
+   public void testListProducersMessageCounts() throws Exception {
       SimpleString queueName1 = new SimpleString("my_queue_one");
       SimpleString addressName1 = new SimpleString("my_address_one");
 
@@ -3971,47 +5507,94 @@ public class ActiveMQServerControlTest extends ManagementTestBase {
          server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
       }
 
+      int numMessages = 10;
+
+
       // create some consumers
       try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator);) {
 
          ClientSession session1 = csf.createSession();
-         ClientSession session2 = csf.createSession();
 
          ClientProducer producer1 = session1.createProducer(addressName1);
-         ClientProducer producer2 = session1.createProducer(addressName1);
-
+         int messagesSize = 0;
+         for (int i = 0; i < numMessages; i++) {
+            ClientMessage message = session1.createMessage(true);
+            producer1.send(message);
+            messagesSize += message.getEncodeSize();
+         }
          //bring back all producers
          String filterString = createJsonFilter("", "", "");
          String producersAsJsonString = serverControl.listProducers(filterString, 1, 50);
          JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
          JsonArray array = (JsonArray) producersAsJsonObject.get("data");
 
-         Assert.assertTrue("number of producers returned from query", 2 <= array.size());
+         Assert.assertEquals("number of producers returned from query", 1 + extraProducers, array.size());
 
-         boolean foundElement = false;
-         for (int i = 0; i < array.size(); i++) {
+         JsonObject jsonSession = array.getJsonObject(0);
 
-            JsonObject jsonSession = array.getJsonObject(i);
-            if (jsonSession.getString("address").equals("activemq.management")) {
-               continue;
-            }
+         //check all fields
+         Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+         Assert.assertNotEquals(ProducerField.SESSION.getName(), "", jsonSession.getString(ProducerField.SESSION.getName()));
+         Assert.assertEquals(ProducerField.CLIENT_ID.getName(), "", jsonSession.getString(ProducerField.CLIENT_ID.getName()));
+         Assert.assertEquals(ProducerField.USER.getName(), "", jsonSession.getString(ProducerField.USER.getName()));
+         Assert.assertNotEquals(ProducerField.PROTOCOL.getAlternativeName(), "", jsonSession.getString(ProducerField.PROTOCOL.getName()));
+         Assert.assertEquals(ProducerField.ADDRESS.getName(), addressName1.toString(), jsonSession.getString(ProducerField.ADDRESS.getName()));
+         Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", jsonSession.getString(ProducerField.LOCAL_ADDRESS.getName()));
+         Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", jsonSession.getString(ProducerField.REMOTE_ADDRESS.getName()));
+         Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         Assert.assertEquals(ProducerField.MESSAGE_SENT.getName(), numMessages, jsonSession.getInt(ProducerField.MESSAGE_SENT.getName()));
+         Assert.assertEquals(ProducerField.MESSAGE_SENT_SIZE.getName(), messagesSize, jsonSession.getInt(ProducerField.MESSAGE_SENT_SIZE.getName()));
+         Assert.assertEquals(ProducerField.LAST_PRODUCED_MESSAGE_ID.getName(), "", jsonSession.getString(ProducerField.LAST_PRODUCED_MESSAGE_ID.getName()));
+      }
+   }
 
-            foundElement = true;
+   @Test
+   public void testListProducersMessageCounts2() throws Exception {
+      SimpleString queueName1 = new SimpleString("my_queue_one");
+      SimpleString addressName1 = new SimpleString("my_address_one");
 
-            //check all fields
-            Assert.assertNotEquals("id", "", jsonSession.getString("id"));
-            Assert.assertNotEquals("session", "", jsonSession.getString("session"));
-            Assert.assertEquals("clientID", "", jsonSession.getString("clientID"));
-            Assert.assertEquals("user", "", jsonSession.getString("user"));
-            Assert.assertNotEquals("protocol", "", jsonSession.getString("protocol"));
-            Assert.assertEquals("address", "", jsonSession.getString("address"));
-            Assert.assertNotEquals("localAddress", "", jsonSession.getString("localAddress"));
-            Assert.assertNotEquals("remoteAddress", "", jsonSession.getString("remoteAddress"));
-            Assert.assertNotEquals("creationTime", "", jsonSession.getString("creationTime"));
+      ActiveMQServerControl serverControl = createManagementControl();
+
+      server.addAddressInfo(new AddressInfo(addressName1, RoutingType.ANYCAST));
+      if (legacyCreateQueue) {
+         server.createQueue(addressName1, RoutingType.ANYCAST, queueName1, null, false, false);
+      } else {
+         server.createQueue(new QueueConfiguration(queueName1).setAddress(addressName1).setRoutingType(RoutingType.ANYCAST).setDurable(false));
+      }
+
+      int numMessages = 10;
+
+
+      // create some consumers
+      try (ServerLocator locator = createInVMNonHALocator(); ClientSessionFactory csf = createSessionFactory(locator);) {
+
+         ClientSession session1 = csf.createSession();
+
+         ClientProducer producer1 = session1.createProducer(addressName1);
+         int messagesSize = 0;
+         for (int i = 0; i < numMessages; i++) {
+            ClientMessage message = session1.createMessage(true);
+            producer1.send(message);
+            messagesSize += message.getEncodeSize();
          }
+         //bring back all producers
+         String producersAsJsonString = serverControl.listProducersInfoAsJSON();
+         JsonArray jsonArray = JsonUtil.readJsonArray(producersAsJsonString);
 
+         JsonObject jsonSession = jsonArray.getJsonObject(0);
 
-         Assert.assertTrue("Valid session not found", foundElement);
+         if (!jsonSession.getString(ProducerField.ADDRESS.getAlternativeName()).equalsIgnoreCase(addressName1.toString())) {
+            jsonSession = jsonArray.getJsonObject(1);
+         }
+
+         //check all fields
+         Assert.assertNotEquals(ProducerField.ID.getName(), "", jsonSession.getString(ProducerField.ID.getName()));
+         Assert.assertNotEquals(ProducerField.NAME.getName(), "", jsonSession.getString(ProducerField.NAME.getName()));
+         Assert.assertNotEquals(ProducerField.SESSION.getAlternativeName(), "", jsonSession.getString(ProducerField.SESSION.getAlternativeName()));
+         Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", jsonSession.getString(ProducerField.CREATION_TIME.getName()));
+         Assert.assertEquals(ProducerField.MESSAGE_SENT.getName(), numMessages, jsonSession.getInt(ProducerField.MESSAGE_SENT.getName()));
+         Assert.assertEquals(ProducerField.MESSAGE_SENT_SIZE.getName(), messagesSize, jsonSession.getInt(ProducerField.MESSAGE_SENT_SIZE.getName()));
+         Assert.assertEquals(ProducerField.LAST_PRODUCED_MESSAGE_ID.getName(), JsonValue.NULL, jsonSession.get(ProducerField.LAST_PRODUCED_MESSAGE_ID.getName()));
       }
    }
 
@@ -4565,16 +6148,6 @@ public class ActiveMQServerControlTest extends ManagementTestBase {
       return ManagementControlHelper.createActiveMQServerControl(mbeanServer);
    }
 
-
-   private String createJsonFilter(String fieldName, String operationName, String value) {
-      HashMap<String, Object> filterMap = new HashMap<>();
-      filterMap.put("field", fieldName);
-      filterMap.put("operation", operationName);
-      filterMap.put("value", value);
-      JsonObject jsonFilterObject = JsonUtil.toJsonObject(filterMap);
-      return jsonFilterObject.toString();
-   }
-
    private String createJsonFilter(String fieldName, String operationName, String value,String sortColumn, String sortOrder) {
       HashMap<String, Object> filterMap = new HashMap<>();
       filterMap.put("field", fieldName);
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java
index f141a8ba66..d42e45a3eb 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java
@@ -31,6 +31,7 @@ public class ActiveMQServerControlUsingCoreTest extends ActiveMQServerControlTes
 
    public ActiveMQServerControlUsingCoreTest(boolean legacyCreateQueue) {
       super(legacyCreateQueue);
+      extraProducers = 1;
    }
 
 
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/QueueControlTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/QueueControlTest.java
index b59147fb1b..693118a601 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/QueueControlTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/QueueControlTest.java
@@ -19,14 +19,24 @@ package org.apache.activemq.artemis.tests.integration.management;
 import javax.jms.Connection;
 import javax.jms.ConnectionFactory;
 import javax.jms.DeliveryMode;
+import javax.jms.MessageConsumer;
 import javax.jms.MessageProducer;
 import javax.jms.Session;
 import javax.jms.TextMessage;
 
+import org.apache.activemq.artemis.api.core.TransportConfiguration;
+import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
+import org.apache.activemq.artemis.api.jms.JMSFactoryType;
+import org.apache.activemq.artemis.core.management.impl.view.ConsumerField;
 import org.apache.activemq.artemis.core.paging.impl.PagingManagerTestAccessor;
 import org.apache.activemq.artemis.core.server.impl.QueueImplTestAccessor;
+import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
 import org.apache.activemq.artemis.json.JsonArray;
 import org.apache.activemq.artemis.json.JsonObject;
+
+import javax.jms.XAConnection;
+import javax.jms.XAConnectionFactory;
+import javax.jms.XASession;
 import javax.management.Notification;
 import javax.management.openmbean.CompositeData;
 import javax.management.openmbean.CompositeDataSupport;
@@ -466,6 +476,10 @@ public class QueueControlTest extends ManagementTestBase {
 
       assertEquals(1, obj.size());
 
+      assertEquals(0, obj.get(0).asJsonObject().getInt(ConsumerField.LAST_DELIVERED_TIME.getName()));
+
+      assertEquals(0, obj.get(0).asJsonObject().getInt(ConsumerField.LAST_ACKNOWLEDGED_TIME.getName()));
+
       consumer.close();
       Assert.assertEquals(0, queueControl.getConsumerCount());
 
@@ -476,6 +490,442 @@ public class QueueControlTest extends ManagementTestBase {
       session.deleteQueue(queue);
    }
 
+   @Test
+   public void testGetConsumerWithMessagesJSON() throws Exception {
+      long currentTime = System.currentTimeMillis();
+      SimpleString address = RandomUtil.randomSimpleString();
+      SimpleString queue = RandomUtil.randomSimpleString();
+
+      session.createQueue(new QueueConfiguration(queue).setAddress(address).setDurable(durable));
+
+      QueueControl queueControl = createManagementControl(address, queue);
+
+      ClientProducer producer = session.createProducer(address);
+
+      for (int i = 0; i < 10; i++) {
+         producer.send(session.createMessage(true));
+      }
+
+      Wait.assertEquals(0, () -> queueControl.getConsumerCount());
+
+      ClientConsumer consumer = session.createConsumer(queue);
+      Wait.assertEquals(1, () -> queueControl.getConsumerCount());
+
+      session.start();
+
+      ClientMessage clientMessage = null;
+
+      int size = 0;
+      for (int i = 0; i < 5; i++) {
+         clientMessage = consumer.receiveImmediate();
+         size += clientMessage.getEncodeSize();
+      }
+
+      JsonArray obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+      assertEquals(1, obj.size());
+
+      Wait.assertEquals(5, () -> JsonUtil.readJsonArray(queueControl.listConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
+
+      obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+      JsonObject jsonObject = obj.get(0).asJsonObject();
+
+      assertEquals(5, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
+
+      assertEquals(size, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()));
+
+      assertEquals(5, jsonObject.getInt(ConsumerField.MESSAGES_DELIVERED.getName()));
+
+      assertEquals(size, jsonObject.getInt(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()));
+
+      assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()));
+
+      long lastDelivered = jsonObject.getJsonNumber(ConsumerField.LAST_DELIVERED_TIME.getName()).longValue();
+
+      assertTrue(lastDelivered > currentTime);
+
+      assertEquals( 0, jsonObject.getInt(ConsumerField.LAST_ACKNOWLEDGED_TIME.getName()));
+
+      clientMessage.acknowledge();
+
+      session.commit();
+
+      Wait.assertEquals(5, () -> JsonUtil.readJsonArray(queueControl.listConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()));
+
+      obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+      jsonObject = obj.get(0).asJsonObject();
+
+      assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
+
+      long lastAcked = jsonObject.getJsonNumber(ConsumerField.LAST_ACKNOWLEDGED_TIME.getName()).longValue();
+
+      assertTrue("lastAcked = " + lastAcked + " lastDelivered = " + lastDelivered, lastAcked >= lastDelivered);
+
+      currentTime = System.currentTimeMillis();
+
+      //now make sure they fall between the test time window
+      assertTrue("currentTime = " + currentTime + " lastAcked = " + lastAcked,currentTime >= lastAcked);
+
+      consumer.close();
+
+      Assert.assertEquals(0, queueControl.getConsumerCount());
+
+      obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+      assertEquals(0, obj.size());
+
+      session.deleteQueue(queue);
+   }
+
+   @Test
+   public void testGetConsumerMessageCountsAutoAckCore() throws Exception {
+      ActiveMQConnectionFactory factory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));
+      factory.setConsumerWindowSize(1);
+      testGetConsumerMessageCountsAutoAck(factory, false);
+   }
+
+   @Test
+   public void testGetConsumerMessageCountsAutoAckAMQP() throws Exception {
+      testGetConsumerMessageCountsAutoAck(new JmsConnectionFactory("amqp://localhost:61616"), false);
+   }
+
+   @Test
+   public void testGetConsumerMessageCountsAutoAckOpenWire() throws Exception {
+      testGetConsumerMessageCountsAutoAck(new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616"), false);
+   }
+
+   @Test
+   public void testGetConsumerMessageCountsAutoAckCoreIndividualAck() throws Exception {
+      ActiveMQConnectionFactory factory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));
+      testGetConsumerMessageCountsAutoAck(factory, true);
+   }
+
+   public void testGetConsumerMessageCountsAutoAck(ConnectionFactory factory, boolean usePriority) throws Exception {
+      SimpleString queueName = RandomUtil.randomSimpleString();
+      this.session.createQueue(new QueueConfiguration(queueName).setAddress(queueName).setDurable(durable).setRoutingType(RoutingType.ANYCAST));
+
+      QueueControl queueControl = createManagementControl(queueName, queueName, RoutingType.ANYCAST);
+      Connection connection = factory.createConnection();
+      try {
+         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+         javax.jms.Queue queue = session.createQueue(queueName.toString());
+
+         MessageProducer producer = session.createProducer(queue);
+
+         for (int i = 0; i < 100; i++) {
+            javax.jms.Message message = session.createMessage();
+            if (usePriority) {
+               producer.send(message, DeliveryMode.PERSISTENT, 1, javax.jms.Message.DEFAULT_TIME_TO_LIVE);
+            } else {
+               producer.send(message);
+            }
+         }
+
+         MessageConsumer consumer = session.createConsumer(queue);
+
+         connection.start();
+
+         javax.jms.Message message = null;
+
+         for (int i = 0; i < 100; i++) {
+            message = consumer.receive(5000);
+            Assert.assertNotNull("message " + i + " not received",message);
+         }
+
+         JsonArray obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+         assertEquals(1, obj.size());
+
+         Wait.assertEquals(0, () -> JsonUtil.readJsonArray(queueControl.listConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
+         Wait.assertEquals(0, () -> JsonUtil.readJsonArray(queueControl.listConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()));
+
+
+         obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+         JsonObject jsonObject = obj.get(0).asJsonObject();
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()));
+
+         assertEquals(100, jsonObject.getInt(ConsumerField.MESSAGES_DELIVERED.getName()));
+
+         assertTrue(jsonObject.getInt(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()) > 0);
+
+         assertEquals(100, jsonObject.getInt(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()));
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()));
+
+         consumer.close();
+      } finally {
+         connection.close();
+      }
+   }
+
+   @Test
+   public void testGetConsumerMessageCountsClientAckCore() throws Exception {
+      ActiveMQConnectionFactory factory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));
+      factory.setConsumerWindowSize(1);
+      testGetConsumerMessageCountsClientAck(factory, false);
+   }
+
+   @Test
+   public void testGetConsumerMessageCountsClientAckAMQP() throws Exception {
+      testGetConsumerMessageCountsClientAck(new JmsConnectionFactory("amqp://localhost:61616"), false);
+   }
+
+   @Test
+   public void testGetConsumerMessageCountsClientAckOpenWire() throws Exception {
+      testGetConsumerMessageCountsClientAck(new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616"), false);
+   }
+
+   public void testGetConsumerMessageCountsClientAck(ConnectionFactory factory, boolean usePriority) throws Exception {
+      SimpleString queueName = RandomUtil.randomSimpleString();
+      this.session.createQueue(new QueueConfiguration(queueName).setAddress(queueName).setDurable(durable).setRoutingType(RoutingType.ANYCAST));
+
+      QueueControl queueControl = createManagementControl(queueName, queueName, RoutingType.ANYCAST);
+      Connection connection = factory.createConnection();
+      try {
+         Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+
+         javax.jms.Queue queue = session.createQueue(queueName.toString());
+
+         MessageProducer producer = session.createProducer(queue);
+
+         for (int i = 0; i < 100; i++) {
+            javax.jms.Message message = session.createMessage();
+            if (usePriority) {
+               producer.send(message, DeliveryMode.PERSISTENT, 1, javax.jms.Message.DEFAULT_TIME_TO_LIVE);
+            } else {
+               producer.send(message);
+            }
+         }
+
+         MessageConsumer consumer = session.createConsumer(queue);
+
+         connection.start();
+
+         javax.jms.Message message = null;
+
+         for (int i = 0; i < 100; i++) {
+            message = consumer.receive(5000);
+            Assert.assertNotNull("message " + i + " not received",message);
+            message.acknowledge();
+         }
+
+         JsonArray obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+         assertEquals(1, obj.size());
+
+         Wait.assertEquals(0, () -> JsonUtil.readJsonArray(queueControl.listConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()));
+         Wait.assertEquals(0, () -> JsonUtil.readJsonArray(queueControl.listConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
+         Wait.assertEquals(0, () -> JsonUtil.readJsonArray(queueControl.listConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()));
+
+         obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+         JsonObject jsonObject = obj.get(0).asJsonObject();
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()));
+
+         assertEquals(100, jsonObject.getInt(ConsumerField.MESSAGES_DELIVERED.getName()));
+
+         assertTrue(jsonObject.getInt(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()) > 0);
+
+         assertEquals(100, jsonObject.getInt(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()));
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()));
+
+         consumer.close();
+      } finally {
+         connection.close();
+      }
+   }
+
+   @Test
+   public void testGetConsumerMessageCountsTransactedCore() throws Exception {
+      ActiveMQConnectionFactory factory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));
+      factory.setConsumerWindowSize(1);
+      testGetConsumerMessageCountsTransacted(factory, false);
+   }
+
+   @Test
+   public void testGetConsumerMessageCountsTransactedAMQP() throws Exception {
+      testGetConsumerMessageCountsTransacted(new JmsConnectionFactory("amqp://localhost:61616"), false);
+   }
+
+   @Test
+   public void testGetConsumerMessageCountsTransactedOpenWire() throws Exception {
+      testGetConsumerMessageCountsTransacted(new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616"), false);
+   }
+
+   public void testGetConsumerMessageCountsTransacted(ConnectionFactory factory, boolean usePriority) throws Exception {
+      SimpleString queueName = RandomUtil.randomSimpleString();
+      this.session.createQueue(new QueueConfiguration(queueName).setAddress(queueName).setDurable(durable).setRoutingType(RoutingType.ANYCAST));
+
+      QueueControl queueControl = createManagementControl(queueName, queueName, RoutingType.ANYCAST);
+      Connection connection = factory.createConnection();
+      try {
+         Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
+
+         javax.jms.Queue queue = session.createQueue(queueName.toString());
+
+         MessageProducer producer = session.createProducer(queue);
+
+         for (int i = 0; i < 100; i++) {
+            javax.jms.Message message = session.createMessage();
+            if (usePriority) {
+               producer.send(message, DeliveryMode.PERSISTENT, 1, javax.jms.Message.DEFAULT_TIME_TO_LIVE);
+            } else {
+               producer.send(message);
+            }
+         }
+         session.commit();
+         MessageConsumer consumer = session.createConsumer(queue);
+
+         connection.start();
+
+         javax.jms.Message message = null;
+
+         for (int i = 0; i < 100; i++) {
+            message = consumer.receive(5000);
+            Assert.assertNotNull("message " + i + " not received",message);
+         }
+
+         session.commit();
+
+         JsonArray obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+         assertEquals(1, obj.size());
+
+         Wait.assertEquals(0, () -> JsonUtil.readJsonArray(queueControl.listConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()));
+
+         obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+         JsonObject jsonObject = obj.get(0).asJsonObject();
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()));
+
+         assertEquals(100, jsonObject.getInt(ConsumerField.MESSAGES_DELIVERED.getName()));
+
+         assertTrue(jsonObject.getInt(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()) > 0);
+
+         assertEquals(100, jsonObject.getInt(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()));
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()));
+
+         consumer.close();
+      } finally {
+         connection.close();
+      }
+   }
+
+   @Test
+   public void testGetConsumerMessageCountsTransactedXACore() throws Exception {
+      ActiveMQConnectionFactory factory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));
+      factory.setConsumerWindowSize(1);
+      testGetConsumerMessageCountsTransactedXA(factory, false);
+   }
+
+   @Test
+   public void testGetConsumerMessageCountsTransactedXAOpenWire() throws Exception {
+      testGetConsumerMessageCountsTransactedXA(new org.apache.activemq.ActiveMQXAConnectionFactory("tcp://localhost:61616"), false);
+   }
+   public void testGetConsumerMessageCountsTransactedXA(XAConnectionFactory factory, boolean usePriority) throws Exception {
+      SimpleString queueName = RandomUtil.randomSimpleString();
+      this.session.createQueue(new QueueConfiguration(queueName).setAddress(queueName).setDurable(durable).setRoutingType(RoutingType.ANYCAST));
+
+      QueueControl queueControl = createManagementControl(queueName, queueName, RoutingType.ANYCAST);
+      XAConnection connection = factory.createXAConnection();
+      try {
+         XASession session = connection.createXASession();
+
+         XidImpl xid = newXID();
+         javax.jms.Queue queue = session.createQueue(queueName.toString());
+
+         MessageProducer producer = session.createProducer(queue);
+         session.getXAResource().start(xid, XAResource.TMNOFLAGS);
+         for (int i = 0; i < 100; i++) {
+            javax.jms.Message message = session.createMessage();
+            if (usePriority) {
+               producer.send(message, DeliveryMode.PERSISTENT, 1, javax.jms.Message.DEFAULT_TIME_TO_LIVE);
+            } else {
+               producer.send(message);
+            }
+         }
+         session.getXAResource().end(xid, XAResource.TMSUCCESS);
+         session.getXAResource().commit(xid, true);
+
+         MessageConsumer consumer = session.createConsumer(queue);
+
+         connection.start();
+         xid = newXID();
+         javax.jms.Message message = null;
+         session.getXAResource().start(xid, XAResource.TMNOFLAGS);
+         for (int i = 0; i < 100; i++) {
+            message = consumer.receive(5000);
+            Assert.assertNotNull("message " + i + " not received",message);
+         }
+         session.getXAResource().end(xid, XAResource.TMSUCCESS);
+
+         JsonArray obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+         assertEquals(1, obj.size());
+
+         Wait.assertEquals(100, () -> JsonUtil.readJsonArray(queueControl.listConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()));
+
+         obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+         JsonObject jsonObject = obj.get(0).asJsonObject();
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()));
+
+         assertEquals(100, jsonObject.getInt(ConsumerField.MESSAGES_DELIVERED.getName()));
+
+         assertTrue(jsonObject.getInt(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()) > 0);
+
+         assertEquals(100, jsonObject.getInt(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()));
+
+         assertEquals(100, jsonObject.getInt(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()));
+
+         session.getXAResource().commit(xid, true);
+
+         obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+         assertEquals(1, obj.size());
+
+         Wait.assertEquals(0, () -> JsonUtil.readJsonArray(queueControl.listConsumersAsJSON()).get(0).asJsonObject().getInt(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()));
+
+         obj = JsonUtil.readJsonArray(queueControl.listConsumersAsJSON());
+
+         jsonObject = obj.get(0).asJsonObject();
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT.getName()));
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_IN_TRANSIT_SIZE.getName()));
+
+         assertEquals(100, jsonObject.getInt(ConsumerField.MESSAGES_DELIVERED.getName()));
+
+         assertTrue(jsonObject.getInt(ConsumerField.MESSAGES_DELIVERED_SIZE.getName()) > 0);
+
+         assertEquals(100, jsonObject.getInt(ConsumerField.MESSAGES_ACKNOWLEDGED.getName()));
+
+         assertEquals(0, jsonObject.getInt(ConsumerField.MESSAGES_ACKNOWLEDGED_AWAITING_COMMIT.getName()));
+
+         consumer.close();
+      } finally {
+         connection.close();
+      }
+   }
+
    @Test
    public void testGetMessageCount() throws Exception {
       SimpleString address = RandomUtil.randomSimpleString();
@@ -589,7 +1039,7 @@ public class QueueControlTest extends ManagementTestBase {
 
                if (key.equals("StringProperties")) {
                   // these are very verbose composite data structures
-                  assertTrue(value.toString().length() + " truncated? " + key, value.toString().length() <= 2048);
+                  assertTrue(value.toString().length() + " truncated? " + key, value.toString().length() <= 3000);
                } else {
                   assertTrue(value.toString().length() + " truncated? " + key, value.toString().length() <= 512);
                }
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/MQTTTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/MQTTTest.java
index bab1e2d834..aee3ba78be 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/MQTTTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/mqtt/MQTTTest.java
@@ -37,12 +37,14 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Pattern;
 
+import org.apache.activemq.artemis.api.core.JsonUtil;
 import org.apache.activemq.artemis.api.core.QueueConfiguration;
 import org.apache.activemq.artemis.api.core.RoutingType;
 import org.apache.activemq.artemis.api.core.SimpleString;
 import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
 import org.apache.activemq.artemis.core.config.Configuration;
 import org.apache.activemq.artemis.core.config.CoreAddressConfiguration;
+import org.apache.activemq.artemis.core.management.impl.view.ProducerField;
 import org.apache.activemq.artemis.core.postoffice.Binding;
 import org.apache.activemq.artemis.core.postoffice.QueueBinding;
 import org.apache.activemq.artemis.core.protocol.mqtt.MQTTUtil;
@@ -50,6 +52,8 @@ import org.apache.activemq.artemis.core.server.ActiveMQServer;
 import org.apache.activemq.artemis.core.server.Queue;
 import org.apache.activemq.artemis.core.server.impl.AddressInfo;
 import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
+import org.apache.activemq.artemis.json.JsonArray;
+import org.apache.activemq.artemis.json.JsonObject;
 import org.apache.activemq.artemis.logs.AssertionLoggerHandler;
 import org.apache.activemq.artemis.tests.util.Wait;
 import org.apache.activemq.transport.amqp.client.AmqpClient;
@@ -168,6 +172,63 @@ public class MQTTTest extends MQTTTestSupport {
       publishProvider.disconnect();
    }
 
+   @Test
+   public void testProducerMetrics() throws Exception {
+
+      final MQTTClientProvider publishProvider = getMQTTClientProvider();
+      initializeConnection(publishProvider);
+
+      for (int i = 0; i < NUM_MESSAGES; i++) {
+         String payload = "Message " + i;
+         publishProvider.publish("foo/bah", payload.getBytes(), AT_LEAST_ONCE);
+      }
+
+      String filterString = createJsonFilter("", "", "");
+      String producersAsJsonString = server.getActiveMQServerControl().listProducers(filterString, 1, 50);
+      JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+      JsonArray array = (JsonArray) producersAsJsonObject.get("data");
+
+      Assert.assertEquals("number of producers returned from query", 1, array.size());
+
+      JsonObject producer = array.getJsonObject(0);
+
+      Assert.assertNotEquals(ProducerField.ID.getName(), "", producer.getString(ProducerField.ID.getName()));
+      Assert.assertNotEquals(ProducerField.SESSION.getName(), "", producer.getString(ProducerField.SESSION.getName()));
+      Assert.assertNotEquals(ProducerField.CLIENT_ID.getName(), "", producer.getString(ProducerField.CLIENT_ID.getName()));
+      Assert.assertEquals(ProducerField.USER.getName(), "", producer.getString(ProducerField.USER.getName()));
+      Assert.assertEquals(ProducerField.PROTOCOL.getAlternativeName(), "MQTT", producer.getString(ProducerField.PROTOCOL.getName()));
+      Assert.assertEquals(ProducerField.ADDRESS.getName(), "ANONYMOUS", producer.getString(ProducerField.ADDRESS.getName()));
+      Assert.assertNotEquals(ProducerField.LOCAL_ADDRESS.getName(), "", producer.getString(ProducerField.LOCAL_ADDRESS.getName()));
+      Assert.assertNotEquals(ProducerField.REMOTE_ADDRESS.getName(), "", producer.getString(ProducerField.REMOTE_ADDRESS.getName()));
+      Assert.assertNotEquals(ProducerField.CREATION_TIME.getName(), "", producer.getString(ProducerField.CREATION_TIME.getName()));
+      Assert.assertEquals(ProducerField.MESSAGE_SENT.getName(), NUM_MESSAGES, producer.getInt(ProducerField.MESSAGE_SENT.getName()));
+      Assert.assertEquals(ProducerField.LAST_PRODUCED_MESSAGE_ID.getName(), "", producer.getString(ProducerField.LAST_PRODUCED_MESSAGE_ID.getName()));
+
+      final MQTTClientProvider publishProvider2 = getMQTTClientProvider();
+      initializeConnection(publishProvider2);
+      for (int i = 0; i < NUM_MESSAGES; i++) {
+         String payload = "Message " + i;
+         publishProvider2.publish("foo/bah", payload.getBytes(), AT_LEAST_ONCE);
+      }
+      filterString = createJsonFilter("", "", "");
+      producersAsJsonString = server.getActiveMQServerControl().listProducers(filterString, 1, 50);
+      producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+      array = (JsonArray) producersAsJsonObject.get("data");
+
+      Assert.assertEquals("number of producers returned from query", 2, array.size());
+      publishProvider.disconnect();
+
+
+      publishProvider2.disconnect();
+
+      filterString = createJsonFilter("", "", "");
+      producersAsJsonString = server.getActiveMQServerControl().listProducers(filterString, 1, 50);
+      producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+      array = (JsonArray) producersAsJsonObject.get("data");
+
+      Assert.assertEquals("number of producers returned from query", 0, array.size());
+   }
+
    @Test(timeout = 60 * 1000)
    public void testDirectDeliverFalse() throws Exception {
       final MQTTClientProvider subscriptionProvider = getMQTTClientProvider();
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/stomp/StompTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/stomp/StompTest.java
index 00fb0f66bd..e326be7fc1 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/stomp/StompTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/stomp/StompTest.java
@@ -34,6 +34,7 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
+import org.apache.activemq.artemis.api.core.JsonUtil;
 import org.apache.activemq.artemis.api.core.QueueConfiguration;
 import org.apache.activemq.artemis.api.core.RoutingType;
 import org.apache.activemq.artemis.api.core.SimpleString;
@@ -47,6 +48,7 @@ import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl;
 import org.apache.activemq.artemis.api.core.management.ManagementHelper;
 import org.apache.activemq.artemis.api.core.management.ResourceNames;
 import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
+import org.apache.activemq.artemis.core.management.impl.view.ProducerField;
 import org.apache.activemq.artemis.core.postoffice.Binding;
 import org.apache.activemq.artemis.core.postoffice.QueueBinding;
 import org.apache.activemq.artemis.core.postoffice.impl.LocalQueueBinding;
@@ -59,6 +61,8 @@ import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
 import org.apache.activemq.artemis.core.server.impl.AddressInfo;
 import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
 import org.apache.activemq.artemis.jms.client.ActiveMQMessage;
+import org.apache.activemq.artemis.json.JsonArray;
+import org.apache.activemq.artemis.json.JsonObject;
 import org.apache.activemq.artemis.logs.AssertionLoggerHandler;
 import org.apache.activemq.artemis.reader.MessageUtil;
 import org.apache.activemq.artemis.spi.core.remoting.Acceptor;
@@ -163,6 +167,44 @@ public class StompTest extends StompTestBase {
       assertTrue(latch.await(60, TimeUnit.SECONDS));
    }
 
+   @Test
+   public void testProducerMetrics() throws Exception {
+      conn.connect(defUser, defPass);
+
+      send(conn, getQueuePrefix() + getQueueName(), null, "Hello World!", true);
+
+      String filterString = createJsonFilter("", "", "");
+      String producersAsJsonString = server.getActiveMQServerControl().listProducers(filterString, 1, 50);
+      JsonObject producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+      JsonArray array = (JsonArray) producersAsJsonObject.get("data");
+
+      Assert.assertEquals("number of producers returned from query", 1, array.size());
+
+      JsonObject producer = array.getJsonObject(0);
+      Assert.assertEquals(ProducerField.MESSAGE_SENT.getName(), 1, producer.getInt(ProducerField.MESSAGE_SENT.getName()));
+
+      send(conn, getQueuePrefix() + getQueueName(), null, "Hello World!", true);
+
+      producersAsJsonString = server.getActiveMQServerControl().listProducers(filterString, 1, 50);
+      producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+      array = (JsonArray) producersAsJsonObject.get("data");
+
+      Assert.assertEquals("number of producers returned from query", 1, array.size());
+
+      producer = array.getJsonObject(0);
+      Assert.assertEquals(ProducerField.MESSAGE_SENT.getName(), 2, producer.getInt(ProducerField.MESSAGE_SENT.getName()));
+
+      conn.closeTransport();
+
+      Wait.assertEquals(0, () -> ((JsonArray) JsonUtil.readJsonObject(server.getActiveMQServerControl().listProducers(filterString, 1, 50)).get("data")).size());
+
+      producersAsJsonString = server.getActiveMQServerControl().listProducers(filterString, 1, 50);
+      producersAsJsonObject = JsonUtil.readJsonObject(producersAsJsonString);
+      array = (JsonArray) producersAsJsonObject.get("data");
+
+      Assert.assertEquals("number of producers returned from query", 0, array.size());
+   }
+
    @Test
    public void testSendOverDiskFull() throws Exception {
       AssertionLoggerHandler.startCapture();