On 3/10/26 21:29, John wrote:
Yes, you are correct. I've confirmed that we are using Artemis for the
subscriptions. ActiveMQ is being used for other purposes. The exception
from earlier was when using Artemis.

So to me, this means it's a bug. If the Client IDs are the same, an
exception is thrown when Artemis is used as the broker. Would the
developers be interested in looking into this? If so, how should we submit
the issue to them?

Thanks

Sorry I was unclear earlier as I was in a rush and I misled you a bit.

A JMS client if setting a client ID must give a unique ID which is why you got the error shown as your clients are all trying to connect with the same client ID.  This is the issue though that prevents you from using shared subscriptions in they way you want since if you set client IDs the shared subscriptions cannot be shared across connections, only from consumers created by sessions under the same connection.  Think of the client ID as a namespace and the lack of one as a global namespace.  Shared subscriptions will work for you if your clients do not set a client ID as you've seen because the namespace of all shared subscriptions without a client ID is shared as a global namespace for that subscription across connections.  Once you set a client ID you are effectively in a private namespace owned by the connection that set that ID and no two connections can share the same client ID.

ActiveMQ does not implement shared subscriptions at all so if you try to use those APIs from the NMS client against that broker the result will likely be an error response or something not doing what you want so you need to use Apache Artemis if you want shared subscriptions but you will need to stick to no client ID if you want to share across connections.  Likely you can accomplish what you want by simply moving to using a Queue as consumers on a Queue all compete for messages (work sharing) which seems like what you are going for. but your exact requirements wasn't fully clear so you'd need to provide more info on why you want to use shared subs.



On Tue, Mar 10, 2026 at 5:33 PM Timothy Bish <[email protected]> wrote:

On 3/10/26 20:15, John wrote:
Thank you for your reply.

If I understand correctly, we should use the same client ID for each
client. And, if that is the case, then this has already been tried,
and the result is that every client after the first throws this
exception:
I know that ActiveMQ doesn't support shared subscriptions of any sort so
if you tried this with ActiveMQ you will not get anything to work, and
if it did somehow create a subscription it would not be a valid one.
You would need to use Apache Artemis for shared subscription support as
that has full support for the AMQP JMS mapping.  As the specification
states the subscription is named by the subscription name and the client
ID so if you want to share your clients either need no client ID or they
all need the same for the subscription in question.


Unhandled exception. Apache.NMS.NMSException: , ErrorInfo = {
key: invalid-field, value: container-id;
}
   ---> Apache.NMS.AMQP.Util.NMSProviderError: amqp:invalid-field
     at Apache.NMS.AMQP.Util.ExceptionSupport.GetException(Error
amqpErr, String message, Exception e)
     at Apache.NMS.AMQP.Provider.Amqp.AmqpConnection.OnClosed(IAmqpObject
sender, Error error)
     at Amqp.AmqpObject.NotifyClosed(Error error)
     at Amqp.Connection.OnEnded(Error error)
     at Amqp.Connection.OnClose(Close close)
     at Amqp.Connection.OnFrame(ByteBuffer buffer)
     at Amqp.AsyncPump.PumpAsync(UInt32 maxFrameSize, Func`2 onHeader,
Func`2 onBuffer)
     at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object
s)
     at System.Threading.ExecutionContext.RunInternal(ExecutionContext
executionContext, ContextCallback callback, Object state)
     at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread
threadPoolThread)
     at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
     at
System.Runtime.CompilerServices.TaskAwaiter.<>c.<OutputWaitEtwEvents>b__12_0(Action
innerContinuation, Task innerTask)
     at
System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action
action, Boolean allowInlining)
     at System.Threading.Tasks.Task.RunContinuations(Object
continuationObject)
     at System.Threading.Tasks.Task`1.TrySetResult(TResult result)
     at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(Task`1
task, TResult result)
     at Amqp.AsyncPump.ReceiveBufferAsync(Byte[] buffer, Int32 offset,
Int32 count)
     at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object
s)
     at System.Threading.ExecutionContext.RunInternal(ExecutionContext
executionContext, ContextCallback callback, Object state)
     at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread
threadPoolThread)
     at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
     at
System.Runtime.CompilerServices.TaskAwaiter.<>c.<OutputWaitEtwEvents>b__12_0(Action
innerContinuation, Task innerTask)
     at
System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action
action, Boolean allowInlining)
     at System.Threading.Tasks.Task.RunContinuations(Object
continuationObject)
     at System.Threading.Tasks.Task`1.TrySetResult(TResult result)
     at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(Task`1
task, TResult result)
     at
Amqp.TcpTransport.TcpSocket.Amqp.IAsyncTransport.ReceiveAsync(Byte[]
buffer, Int32 offset, Int32 count)
     at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object
s)
     at System.Threading.ExecutionContext.RunInternal(ExecutionContext
executionContext, ContextCallback callback, Object state)
     at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread
threadPoolThread)
     at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
     at
System.Runtime.CompilerServices.TaskAwaiter.<>c.<OutputWaitEtwEvents>b__12_0(Action
innerContinuation, Task innerTask)
     at
System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(Action
action, Boolean allowInlining)
     at System.Threading.Tasks.Task.RunContinuations(Object
continuationObject)
     at System.Threading.Tasks.Task`1.TrySetResult(TResult result)
     at
System.Threading.Tasks.TaskCompletionSource`1.TrySetResult(TResult result)
     at Amqp.SocketExtensions.Complete[T](Object sender,
SocketAsyncEventArgs args, Boolean throwOnError, T result)
     at Amqp.TcpTransport.TcpSocket.<>c.<.ctor>b__6_1(Object s,
SocketAsyncEventArgs a)
     at System.Threading.ExecutionContext.RunInternal(ExecutionContext
executionContext, ContextCallback callback, Object state)
     at
System.Net.Sockets.SocketAsyncEventArgs.<>c.<.cctor>b__174_0(UInt32
errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
     at
System.Threading.PortableThreadPool.IOCompletionPoller.Event.Invoke()
     at
System.Threading.ThreadPoolTypedWorkItemQueue.System.Threading.IThreadPoolWorkItem.Execute()
     at System.Threading.ThreadPoolWorkQueue.Dispatch()
     at
System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
     at System.Threading.Thread.StartCallback()

     --- End of inner exception stack trace ---
     at Apache.NMS.AMQP.NmsConnection.CreateNmsConnectionInternal(Boolean
sync)
     at
Apache.NMS.AMQP.Util.Synchronization.TaskExtensions.AwaitRunContinuationAsync(Task
task)
     at Apache.NMS.AMQP.NmsConnection.StartAsync()
     at
Apache.NMS.AMQP.Util.Synchronization.TaskExtensions.GetAsyncResult(Task
task)
     at Apache.NMS.AMQP.NmsConnection.Start()




On Tue, Mar 10, 2026 at 4:48 PM Timothy Bish <[email protected]>
wrote:
On 3/10/26 19:42, John wrote:
Hi Tim,

Yes, each client has a unique Client ID. And this has been verified.
However, should the Client ID follow a specific pattern?
That's your problem then, you are creating many uniquely identified
shared subscriptions.

   From the JMS specification

"A shared non-durable subscription is identified by a name specified by
the client and by the client
identifier if set. If the client identifier was set when the shared
non-durable subscription was first
created then a client which subsequently wishes to create a consumer on
that shared non-durable
subscription must use the same client identifier."


On Tue, Mar 10, 2026 at 4:17 PM Timothy Bish <[email protected]>
wrote:
On 3/10/26 18:51, John wrote:
Hi,

I have stumbled across an issue that I believe is with
Apache.NMS.AMQP
library. I'm using the latest stable version, 2.4.0, for my .NET C#
service
for message handling, with the latest Apache Artemis and Apache
ActiveMQ
message brokers.
Both the web page on Uri Configuration (

https://activemq.apache.org/components/nms/providers/amqp/uri-configuration
)
and the GitHub project (

https://github.com/apache/activemq-nms-amqp/blob/main/docs/configuration.md
)
state that "nms.clientId" should be used in the Connection Uri to
configure
the Client ID.
However, I have found that using "nms.clientId" breaks consumer
functionality for Shared Consumers, who will then receive every
message
in
the topic. And that, excluding the query parameter, allows Shared
Consumers
to function correctly, with each consumer receiving only their share
of
the
messages.
Please also note that if one does not include the parameter in the
Uri
but
instead sets the ClientId on the connection object itself, the Shared
Customer will still not function correctly, having the same issue as
using
the parameter in the Uri.
However, by not including the nms.clientId parameter, a Client ID is
automatically generated, which I guess is why it works correctly.
Nevertheless, it is less than ideal not being able to use my own
Client
ID.
But maybe I'm doing something wrong. Here is some simple example code
using
the nms.clientId parameter that has the issue:

static async Task SharedAsync(string clientId, CancellationToken
stoppingToken)
{
        string uri =

$"amqp://localhost:61616?nms.username=artemis&nms.password=artemis&nms.clientId={clientId}";
Are you giving each client the same ID or are they each being assigned
there own unique client ID ?


        var connecturi = new Uri(uri);
        var factory = new NMSConnectionFactory(connecturi);
        using IConnection connection = await
factory.CreateConnectionAsync();
        connection.Start();
        using ISession session = await
connection.CreateSessionAsync();
        ITopic destination = await
session.GetTopicAsync("topic-name");
        using var consumer = await
session.CreateSharedConsumerAsync(destination, "sub-name");
        while (!stoppingToken.IsCancellationRequested)
        {
            var msg = await
consumer.ReceiveAsync(TimeSpan.FromMicroseconds(250)) as
ITextMessage;
            if (msg is not null)
            {
                // process message
            }
        }
}


Thanks,
John

--
Tim Bish


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information, visit: https://activemq.apache.org/contact



--
Tim Bish


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information, visit: https://activemq.apache.org/contact


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information, visit: https://activemq.apache.org/contact


--
Tim Bish


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information, visit: https://activemq.apache.org/contact




--
Tim Bish


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information, visit: https://activemq.apache.org/contact


Reply via email to