You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@activemq.apache.org by John <jk...@gmail.com> on 2026/03/10 22:51:23 UTC
Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
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}";
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
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by Robbie Gemmell <ro...@gmail.com>.
Kinda seems like you didnt read my mail which both explained exactly
why it does/has to work the way it does and noted that potential
solution :)
On Sun, 15 Mar 2026 at 22:18, John <jk...@gmail.com> wrote:
>
> Hi Everyone-
>
> We've figured out a solution.
>
> After stepping through the Apache NMS AMQP code (which isn't easy
> because it starts out with some kind of funky dynamic plugin like
> loading, which makes it difficult to step through), we saw that when
> the Client ID is auto-generated, it pulls in a prefix variable. After
> following that rabbit, we figured out that it comes in from the Uri.
> At practically the same time, it was "rediscovered" in the connection
> documentation, there is a Uri parameter named nms.clientIdPrefix. This
> parameter allows the auto-generated Client ID to be prefixed with
> whatever is wanted. Doh! What is so funny (or should I say sad) here
> is that this was originally seen but not understood, as far as how it
> would relate to us with what we want to do. At that earlier time, we
> didn't know the significance of the auto-generated Client IDs and
> Shared Subscribers. As I said before, and I'll say again, what does it
> matter between an auto-generated unique Client ID and a self-created
> unique Client ID? (Don't answer that) I know what the group will say,
> "...because that's what the documentation says..." ;-)
>
> So, anyway, using the prefix to name the auto-generated Client IDs so
> that they can be differentiated solves our problem.
>
> Thank you to everyone who helped with our issue.
>
> Cheers!
>
>
>
> On Sat, Mar 14, 2026 at 6:47 AM Robbie Gemmell <ro...@gmail.com> wrote:
> >
> > The only bit which sounds like it may be a bug in the NMS client is if
> > you can't create multiple consumers on a shared subscription on the
> > same connection in a situation you actually should be able to. That
> > doesnt actually seem to be your main complaint though, so I'll
> > concentrate on your other thoughts that different connections each
> > with distinct ClientIDs explicitly set, getting the same messages,
> > whilst using a shared subscriber with the same shared subscription
> > name, would be a bug. It is not.
> >
> > This is required JMS spec-defined behaviour from 2013 [and before]
> > with the release of JMS 2.0 API specification when shared
> > subscriptions were added, along with the ability to not actually set a
> > ClientID on a Connection and yet still use shared [durable]
> > subscriptions.
> >
> > The spec requires that a shared subscription on a Connection with a
> > ClientID specified behaves one way, giving totally separate
> > ClientID-scoped namespaces for durable and non-durable named shared
> > subscriptions, and further that there is only a single joined
> > subscription namespace for both the shared durable and
> > previously-existing JMS 1 non-shared durable named subscriptions that
> > were already ClientID-scoped since 1998. The spec also requires that
> > shared subscriptions on a Connection without a ClientID specified
> > behave in a completely different way, with each of durable and
> > non-durable shared subscriptions being in separate namespaces
> > (distinct from both each other, and from those on Connections with a
> > ClientID specified) with a given named subscription of a given type
> > then shareable between all such Connections similarly without any
> > ClientID specified. For completeness, you can't have a non-shared
> > durable subscription on a Connection without a ClientID specified.
> >
> > If you do specify a ClientID, the spec thus inherently requires that
> > you can then only have other shared consumers for that ClientID-scoped
> > shared subscription on that very same Connection, since only one
> > Connection can use a ClientID at a given time and the subscription is
> > scoped to that ClientID, meaning no other Connection can share that
> > subscription at the same time, end of story. Different Connections
> > with a distinct specified ClientID can each have their own similar
> > subscriptions with the same subscription name, but that is a totally
> > separate subscription scoped to their ClientID, and they thus receive
> > their own copy of the messages like any distinct subscription should.
> > If that doesnt meet your needs because e.g. you want to share a single
> > subscription across multiple different Connections, then you would
> > need to not set a ClientID on your Connections in which case all such
> > Connections without ClientID can share that distinct
> > not-ClientID-scoped named subscription since they are then all
> > accessing the same subscription, or else you would need to use a
> > regular Queue with competing consumers (this behaving the same
> > regardless of the ClientID being explicitly specified or not since its
> > not a topic subscription), as has been explained before.
> >
> > The ClientID if specified is conveyed on the wire in the container-id
> > field which must have a value, so the client generates a value for
> > this if a ClientID was not explicitly specified. It is known whether a
> > ClientID has been explicitly specified or not, and then in turn it is
> > known when a shared[/non-shared durable] subscription is being created
> > whether a ClientID was specified or not, and a different thing is done
> > in these cases resulting in the different required behaviours detailed
> > by the JMS specification and outlined above and previously in the
> > thread. The NMS behaviour is based on this JMS behaviour.
> >
> > I know that in Qpid JMS we allow defining a 'ClientIDPrefix' to be
> > used within the auto-generated values if you dont actually specify a
> > ClientID. I dont know for sure if that functionality was copied in the
> > NMS AMQP client but I would guess it was. If so perhaps you can use
> > that to help discriminate between different connections if your main
> > concern is harder identification of things using a generated
> > container-id value that's being displayed as a ClientID in the
> > console.
> >
> > In terms of the overall behaviour you can avail yourself of the
> > formerly-JMS / now Jakarta Messaging specification at:
> > https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/package-summary
> >
> > Of particular relation to the discussion would be the 8 shared and
> > non-shared subscription methods that cover all the behaviour as it has
> > already been explained:
> > https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createDurableConsumer(jakarta.jms.Topic,java.lang.String)
> > https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createDurableConsumer(jakarta.jms.Topic,java.lang.String,java.lang.String,boolean)
> > https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createDurableSubscriber(jakarta.jms.Topic,java.lang.String)
> > https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createDurableSubscriber(jakarta.jms.Topic,java.lang.String,java.lang.String,boolean)
> > https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createSharedConsumer(jakarta.jms.Topic,java.lang.String)
> > https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createSharedConsumer(jakarta.jms.Topic,java.lang.String,java.lang.String)
> > https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createSharedDurableConsumer(jakarta.jms.Topic,java.lang.String)
> > https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createSharedDurableConsumer(jakarta.jms.Topic,java.lang.String,java.lang.String)
> >
> > Robbie
> >
> > On Sat, 14 Mar 2026 at 05:48, John <jk...@gmail.com> wrote:
> > >
> > > On Thu, Mar 12, 2026 at 7:47 PM Justin Bertram <jb...@apache.org> wrote:
> > >
> > > > If I may interject...
> > > >
> > > > I'm not super familiar with the NMS client you're using, but my
> > > > understanding is that it should essentially act like a traditional JMS
> > > > client for this use-case. Assuming that's true, I think everything
> > > > you're seeing is the expected behavior.
> > > >
> > > > Here are a few things to keep in mind (distilling what Tim already said):
> > > >
> > > > 1) Any client wishing to connect to the broker with a client ID must
> > > > ensure that ID is unique among all connected clients. Clients
> > > > attempting to connect using a client ID already in use will be
> > > > rejected.
> > > >
> > >
> > > I agree with this. Where a client is considered a connection. As it is our
> > > observation that each connection is either given a unique Client ID when
> > > not explicitly set, or if the Client ID is assigned via the nms.clientId
> > > parameter, then it must be unique; otherwise, an exception is thrown.
> > >
> > >
> > > > 2) If set, the client ID will become part of any shared subscription
> > > > created. Receiving messages from that shared subscription requires the
> > > > same client ID.
> > > >
> > >
> > > This does not track with what we are seeing. So, I almost think that the
> > > terminology in NMS differs from that in JMS. Almost, thinking that possibly
> > > "Shared Subscriptions" or "Client ID" for the observed behaviors for NMS
> > > doesn't mean the same as in JMS.
> > >
> > > I say observed behaviors, because we have not found much documentation on
> > > NMS, and so here is what we have figured out in NMS:
> > >
> > > The Client ID is always set. Either automatically when creating the
> > > connection or explicitly via the NMS.clientId Uri parameter. In either
> > > case, the Client ID will/must be unique.
> > >
> > > When creating a Shared Subscriber (e.g.,
> > > session.CreateSharedConsumer(topic, subscriptionName)), messages from that
> > > topic are supposed to be distributed among the Shared Subscribers. (They
> > > don't each receive all the messages. The messages are divided among the
> > > Shared Subscribers.)
> > >
> > > And to create a Shared Subscriber, one must have a unique Client ID
> > > (whether set implicitly or explicitly) and a common Subscription Name.
> > >
> > > And for (#2), to make sense (somewhat) in NMS, instead of "Client ID," as
> > > stated, maybe it should read "Subscription Name". As I already stated in
> > > NMS, the Client ID is always set, no matter what.
> > >
> > > And in NMS, the only way any type of subscriber would have the same Client
> > > ID is to be on the same connection. But if one were to try to create more
> > > than one Shared Subscriber on a connection (whether the Client ID is
> > > implicitly or explicitly set), an exception is thrown: "The key already
> > > existed in the dictionary."
> > >
> > >
> > > > 3) The client ID may be null when creating a shared subscription.
> > > >
> > >
> > > With NMS, if a Client ID is not explicitly assigned, then it is
> > > automatically generated for the connection. So, this isn't true in NMS.
> > > There will always be a Client ID.
> > >
> > > Now, as I mentioned above (#2), in NMS, if the "Client ID" was meant to
> > > read as "Subscription Name", then yes, the Subscription Name can be null
> > > when creating Shared Subscribers. However, they do not behave like Shared
> > > Subscribers, as each receives all messages for the topic, just like a
> > > regular subscriber (e.g., session.CreateConsumer(topic)), defeating the
> > > purpose of Shared Subscribers.
> > >
> > >
> > >
> > > > 4) If you want to share a subscription among several simultaneously
> > > > connected clients, do not set the client ID.
> > > >
> > > > The whole client ID + shared subscription combo just doesn't make a
> > > > lot of sense. Shared subscriptions were added to the JMS specification
> > > > years after client ID was established so not everything fits perfectly
> > > > conceptually. However, once you understand the basic rules it's pretty
> > > > straight-forward.
> > > >
> > > >
> > > Well, this is true. Not explicitly setting the Client ID and allowing the
> > > connection to generate its own unique Client ID allows for Shared Consumers
> > > to work correctly. But this is what I'm complaining about.
> > >
> > > And for some, sharing (dividing) messages on a topic makes sense.
> > > Let's walk through a use case:
> > > Let's say multiple "microservices" are subscribed to a topic, each handling
> > > the messages received on that topic. Then, let's say one of these services
> > > takes a long time to handle messages from the topic. Then, for this one
> > > service, it makes sense to scale out, meaning running more than one
> > > instance of it. Then, for this one service, it would want the message
> > > divided among its instances, with each instance handling its share, thereby
> > > spreading the workload.
> > > Now, let's say many of the "microservices", each need to scale out to
> > > handle the workload generated by the many more messages on that topic
> > > during a large traffic spike. Each instance of each service needs to handle
> > > its share of messages, but overall, each service needs to receive all
> > > messages from the topic. Now, imagine these service instances are all
> > > coming and going as traffic ramps up and down. And then say someone (or
> > > another service) has the task of monitoring or troubleshooting these
> > > connections and subscribers, but since all these connections that are
> > > coming and going can't be named, but instead must each be given an
> > > auto-generated UUID, they become very difficult to tell apart. If one were
> > > a mere human working in the Broker's Management console, I would dare to
> > > say it is impossible.
> > >
> > > I hope that makes sense. And in our case, it's a bit more complicated
> > > because some services run on the same hosts (to save money), and when a
> > > host scales, those services scale together.
> > >
> > > And back to what I originally was trying to convey in my first email to the
> > > group:
> > >
> > > When creating Shared Consumers with our own unique Client IDs via the Uri
> > > nms.clientId parameter, each Shared Subscriber receives all messages from
> > > the topic, just like a regular subscriber (e.g.,
> > > session.CreateConsumer(topic) ).
> > >
> > > To us, this does not make sense. Why would the Shared Subscribers (e.g.,
> > > session.CreateSharedConsumer(topic, subscriptionName)) each receive all
> > > messages when they have an explicitly set unique Client ID and a common
> > > Subscription Name, but if you don't set the Client ID, it works as it
> > > should, even though a unique Client ID is auto-generated for the
> > > connection? (That's a rhetorical question.)
> > >
> > > This has to be a bug. And if it is by design, it should be changed. Well,
> > > that is my two cents anyway.
> > >
> > > Thanks
> > >
> > > John
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > > > Hope that helps!
> > > >
> > > >
> > > > Justin
> > > >
> > > > On Thu, Mar 12, 2026 at 9:09 PM John <jk...@gmail.com> wrote:
> > > > >
> > > > > Hi Tim,
> > > > >
> > > > > I'm writing back again to talk about this issue more.
> > > > >
> > > > > Per our prior conversation, we've confirmed that, with Artemis (not
> > > > > ActiveMQ) for Shared Consumers, using a single connection and setting the
> > > > > nms.clientId parameter in the URI, any Shared Consumer created after the
> > > > > first one throws an exception ("The key already existed in the
> > > > > dictionary"). This same exception is thrown under the same circumstances
> > > > > when the Client ID is not on the URI and is instead generated by the
> > > > > library.
> > > > >
> > > > > And anyway, even if it would let us, using a single connection would not
> > > > > work for us. This is because we have several services that subscribe to a
> > > > > topic. One of the services takes a bit of time to process the messages
> > > > from
> > > > > the topic. For this particular service, we want to scale out to
> > > > distribute
> > > > > the message workload. And, technically, we want this ability for each
> > > > > service. Also, using a queue for this service is not ideal as it defeats
> > > > > the purpose of having a topic.
> > > > >
> > > > > Also, in our examination, the Client ID does not appear to be a shared
> > > > > namespace, per se, as discussed earlier. Or, to clarify further, if the
> > > > > Client ID is not assigned to the connections via nms.clientId, the
> > > > > library-generated Client IDs are unique for each Shared Consumer's
> > > > > connection and have the following format: "ID:HOSTNAME:UUID:N", where
> > > > UUID
> > > > > is unique for each connection.
> > > > > This is odd regarding the earlier discussion, since the generated Client
> > > > > IDs are unique. Why would our unique Client ID via nms.clientId be
> > > > treated
> > > > > any differently?
> > > > >
> > > > > Nevertheless, as far as we can tell, the only way Shared Consumers work
> > > > > correctly is without setting our own Client IDs. But it would be
> > > > > advantageous for us to use our own Client IDs, and it seems we should be
> > > > > able to do so. And if so, we are back to the idea that this is a bug.
> > > > >
> > > > > Please let me know what your thoughts are.
> > > > >
> > > > > Thanks
> > > > >
> > > > > John
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > > On Tue, Mar 10, 2026 at 9:48 PM John <jk...@gmail.com> wrote:
> > > > >
> > > > > > Thank you for the explanation. I better understand now. And I think
> > > > > > switching to regular consumers will probably work.
> > > > > >
> > > > > > Thanks again.
> > > > > >
> > > > > > On Tue, Mar 10, 2026 at 7:53 PM Timothy Bish <ta...@gmail.com>
> > > > wrote:
> > > > > >
> > > > > >> 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 <ta...@gmail.com>
> > > > > >> 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 <tabish121@gmail.com
> > > > >
> > > > > >> >> 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 <
> > > > tabish121@gmail.com>
> > > > > >> >> 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: users-unsubscribe@activemq.apache.org
> > > > > >> >>>>>> For additional commands, e-mail:
> > > > users-help@activemq.apache.org
> > > > > >> >>>>>> For further information, visit:
> > > > > >> https://activemq.apache.org/contact
> > > > > >> >>>>>>
> > > > > >> >>>>>>
> > > > > >> >>>>>>
> > > > > >> >>>> --
> > > > > >> >>>> Tim Bish
> > > > > >> >>>>
> > > > > >> >>>>
> > > > > >> >>>>
> > > > ---------------------------------------------------------------------
> > > > > >> >>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > > > >> >>>> For additional commands, e-mail: users-help@activemq.apache.org
> > > > > >> >>>> For further information, visit:
> > > > https://activemq.apache.org/contact
> > > > > >> >>>>
> > > > > >> >>>>
> > > > > >> >>>
> > > > ---------------------------------------------------------------------
> > > > > >> >>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > > > >> >>> For additional commands, e-mail: users-help@activemq.apache.org
> > > > > >> >>> For further information, visit:
> > > > https://activemq.apache.org/contact
> > > > > >> >>>
> > > > > >> >>>
> > > > > >> >> --
> > > > > >> >> Tim Bish
> > > > > >> >>
> > > > > >> >>
> > > > > >> >>
> > > > ---------------------------------------------------------------------
> > > > > >> >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > > > >> >> For additional commands, e-mail: users-help@activemq.apache.org
> > > > > >> >> For further information, visit:
> > > > https://activemq.apache.org/contact
> > > > > >> >>
> > > > > >> >>
> > > > > >> >>
> > > > > >>
> > > > > >> --
> > > > > >> Tim Bish
> > > > > >>
> > > > > >>
> > > > > >> ---------------------------------------------------------------------
> > > > > >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > > > >> For additional commands, e-mail: users-help@activemq.apache.org
> > > > > >> For further information, visit: https://activemq.apache.org/contact
> > > > > >>
> > > > > >>
> > > > > >>
> > > >
> > > > ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > > For additional commands, e-mail: users-help@activemq.apache.org
> > > > For further information, visit: https://activemq.apache.org/contact
> > > >
> > > >
> > > >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > For additional commands, e-mail: users-help@activemq.apache.org
> > For further information, visit: https://activemq.apache.org/contact
> >
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> For additional commands, e-mail: users-help@activemq.apache.org
> For further information, visit: https://activemq.apache.org/contact
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
For additional commands, e-mail: users-help@activemq.apache.org
For further information, visit: https://activemq.apache.org/contact
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by John <jk...@gmail.com>.
Hi Everyone-
We've figured out a solution.
After stepping through the Apache NMS AMQP code (which isn't easy
because it starts out with some kind of funky dynamic plugin like
loading, which makes it difficult to step through), we saw that when
the Client ID is auto-generated, it pulls in a prefix variable. After
following that rabbit, we figured out that it comes in from the Uri.
At practically the same time, it was "rediscovered" in the connection
documentation, there is a Uri parameter named nms.clientIdPrefix. This
parameter allows the auto-generated Client ID to be prefixed with
whatever is wanted. Doh! What is so funny (or should I say sad) here
is that this was originally seen but not understood, as far as how it
would relate to us with what we want to do. At that earlier time, we
didn't know the significance of the auto-generated Client IDs and
Shared Subscribers. As I said before, and I'll say again, what does it
matter between an auto-generated unique Client ID and a self-created
unique Client ID? (Don't answer that) I know what the group will say,
"...because that's what the documentation says..." ;-)
So, anyway, using the prefix to name the auto-generated Client IDs so
that they can be differentiated solves our problem.
Thank you to everyone who helped with our issue.
Cheers!
On Sat, Mar 14, 2026 at 6:47 AM Robbie Gemmell <ro...@gmail.com> wrote:
>
> The only bit which sounds like it may be a bug in the NMS client is if
> you can't create multiple consumers on a shared subscription on the
> same connection in a situation you actually should be able to. That
> doesnt actually seem to be your main complaint though, so I'll
> concentrate on your other thoughts that different connections each
> with distinct ClientIDs explicitly set, getting the same messages,
> whilst using a shared subscriber with the same shared subscription
> name, would be a bug. It is not.
>
> This is required JMS spec-defined behaviour from 2013 [and before]
> with the release of JMS 2.0 API specification when shared
> subscriptions were added, along with the ability to not actually set a
> ClientID on a Connection and yet still use shared [durable]
> subscriptions.
>
> The spec requires that a shared subscription on a Connection with a
> ClientID specified behaves one way, giving totally separate
> ClientID-scoped namespaces for durable and non-durable named shared
> subscriptions, and further that there is only a single joined
> subscription namespace for both the shared durable and
> previously-existing JMS 1 non-shared durable named subscriptions that
> were already ClientID-scoped since 1998. The spec also requires that
> shared subscriptions on a Connection without a ClientID specified
> behave in a completely different way, with each of durable and
> non-durable shared subscriptions being in separate namespaces
> (distinct from both each other, and from those on Connections with a
> ClientID specified) with a given named subscription of a given type
> then shareable between all such Connections similarly without any
> ClientID specified. For completeness, you can't have a non-shared
> durable subscription on a Connection without a ClientID specified.
>
> If you do specify a ClientID, the spec thus inherently requires that
> you can then only have other shared consumers for that ClientID-scoped
> shared subscription on that very same Connection, since only one
> Connection can use a ClientID at a given time and the subscription is
> scoped to that ClientID, meaning no other Connection can share that
> subscription at the same time, end of story. Different Connections
> with a distinct specified ClientID can each have their own similar
> subscriptions with the same subscription name, but that is a totally
> separate subscription scoped to their ClientID, and they thus receive
> their own copy of the messages like any distinct subscription should.
> If that doesnt meet your needs because e.g. you want to share a single
> subscription across multiple different Connections, then you would
> need to not set a ClientID on your Connections in which case all such
> Connections without ClientID can share that distinct
> not-ClientID-scoped named subscription since they are then all
> accessing the same subscription, or else you would need to use a
> regular Queue with competing consumers (this behaving the same
> regardless of the ClientID being explicitly specified or not since its
> not a topic subscription), as has been explained before.
>
> The ClientID if specified is conveyed on the wire in the container-id
> field which must have a value, so the client generates a value for
> this if a ClientID was not explicitly specified. It is known whether a
> ClientID has been explicitly specified or not, and then in turn it is
> known when a shared[/non-shared durable] subscription is being created
> whether a ClientID was specified or not, and a different thing is done
> in these cases resulting in the different required behaviours detailed
> by the JMS specification and outlined above and previously in the
> thread. The NMS behaviour is based on this JMS behaviour.
>
> I know that in Qpid JMS we allow defining a 'ClientIDPrefix' to be
> used within the auto-generated values if you dont actually specify a
> ClientID. I dont know for sure if that functionality was copied in the
> NMS AMQP client but I would guess it was. If so perhaps you can use
> that to help discriminate between different connections if your main
> concern is harder identification of things using a generated
> container-id value that's being displayed as a ClientID in the
> console.
>
> In terms of the overall behaviour you can avail yourself of the
> formerly-JMS / now Jakarta Messaging specification at:
> https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/package-summary
>
> Of particular relation to the discussion would be the 8 shared and
> non-shared subscription methods that cover all the behaviour as it has
> already been explained:
> https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createDurableConsumer(jakarta.jms.Topic,java.lang.String)
> https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createDurableConsumer(jakarta.jms.Topic,java.lang.String,java.lang.String,boolean)
> https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createDurableSubscriber(jakarta.jms.Topic,java.lang.String)
> https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createDurableSubscriber(jakarta.jms.Topic,java.lang.String,java.lang.String,boolean)
> https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createSharedConsumer(jakarta.jms.Topic,java.lang.String)
> https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createSharedConsumer(jakarta.jms.Topic,java.lang.String,java.lang.String)
> https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createSharedDurableConsumer(jakarta.jms.Topic,java.lang.String)
> https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createSharedDurableConsumer(jakarta.jms.Topic,java.lang.String,java.lang.String)
>
> Robbie
>
> On Sat, 14 Mar 2026 at 05:48, John <jk...@gmail.com> wrote:
> >
> > On Thu, Mar 12, 2026 at 7:47 PM Justin Bertram <jb...@apache.org> wrote:
> >
> > > If I may interject...
> > >
> > > I'm not super familiar with the NMS client you're using, but my
> > > understanding is that it should essentially act like a traditional JMS
> > > client for this use-case. Assuming that's true, I think everything
> > > you're seeing is the expected behavior.
> > >
> > > Here are a few things to keep in mind (distilling what Tim already said):
> > >
> > > 1) Any client wishing to connect to the broker with a client ID must
> > > ensure that ID is unique among all connected clients. Clients
> > > attempting to connect using a client ID already in use will be
> > > rejected.
> > >
> >
> > I agree with this. Where a client is considered a connection. As it is our
> > observation that each connection is either given a unique Client ID when
> > not explicitly set, or if the Client ID is assigned via the nms.clientId
> > parameter, then it must be unique; otherwise, an exception is thrown.
> >
> >
> > > 2) If set, the client ID will become part of any shared subscription
> > > created. Receiving messages from that shared subscription requires the
> > > same client ID.
> > >
> >
> > This does not track with what we are seeing. So, I almost think that the
> > terminology in NMS differs from that in JMS. Almost, thinking that possibly
> > "Shared Subscriptions" or "Client ID" for the observed behaviors for NMS
> > doesn't mean the same as in JMS.
> >
> > I say observed behaviors, because we have not found much documentation on
> > NMS, and so here is what we have figured out in NMS:
> >
> > The Client ID is always set. Either automatically when creating the
> > connection or explicitly via the NMS.clientId Uri parameter. In either
> > case, the Client ID will/must be unique.
> >
> > When creating a Shared Subscriber (e.g.,
> > session.CreateSharedConsumer(topic, subscriptionName)), messages from that
> > topic are supposed to be distributed among the Shared Subscribers. (They
> > don't each receive all the messages. The messages are divided among the
> > Shared Subscribers.)
> >
> > And to create a Shared Subscriber, one must have a unique Client ID
> > (whether set implicitly or explicitly) and a common Subscription Name.
> >
> > And for (#2), to make sense (somewhat) in NMS, instead of "Client ID," as
> > stated, maybe it should read "Subscription Name". As I already stated in
> > NMS, the Client ID is always set, no matter what.
> >
> > And in NMS, the only way any type of subscriber would have the same Client
> > ID is to be on the same connection. But if one were to try to create more
> > than one Shared Subscriber on a connection (whether the Client ID is
> > implicitly or explicitly set), an exception is thrown: "The key already
> > existed in the dictionary."
> >
> >
> > > 3) The client ID may be null when creating a shared subscription.
> > >
> >
> > With NMS, if a Client ID is not explicitly assigned, then it is
> > automatically generated for the connection. So, this isn't true in NMS.
> > There will always be a Client ID.
> >
> > Now, as I mentioned above (#2), in NMS, if the "Client ID" was meant to
> > read as "Subscription Name", then yes, the Subscription Name can be null
> > when creating Shared Subscribers. However, they do not behave like Shared
> > Subscribers, as each receives all messages for the topic, just like a
> > regular subscriber (e.g., session.CreateConsumer(topic)), defeating the
> > purpose of Shared Subscribers.
> >
> >
> >
> > > 4) If you want to share a subscription among several simultaneously
> > > connected clients, do not set the client ID.
> > >
> > > The whole client ID + shared subscription combo just doesn't make a
> > > lot of sense. Shared subscriptions were added to the JMS specification
> > > years after client ID was established so not everything fits perfectly
> > > conceptually. However, once you understand the basic rules it's pretty
> > > straight-forward.
> > >
> > >
> > Well, this is true. Not explicitly setting the Client ID and allowing the
> > connection to generate its own unique Client ID allows for Shared Consumers
> > to work correctly. But this is what I'm complaining about.
> >
> > And for some, sharing (dividing) messages on a topic makes sense.
> > Let's walk through a use case:
> > Let's say multiple "microservices" are subscribed to a topic, each handling
> > the messages received on that topic. Then, let's say one of these services
> > takes a long time to handle messages from the topic. Then, for this one
> > service, it makes sense to scale out, meaning running more than one
> > instance of it. Then, for this one service, it would want the message
> > divided among its instances, with each instance handling its share, thereby
> > spreading the workload.
> > Now, let's say many of the "microservices", each need to scale out to
> > handle the workload generated by the many more messages on that topic
> > during a large traffic spike. Each instance of each service needs to handle
> > its share of messages, but overall, each service needs to receive all
> > messages from the topic. Now, imagine these service instances are all
> > coming and going as traffic ramps up and down. And then say someone (or
> > another service) has the task of monitoring or troubleshooting these
> > connections and subscribers, but since all these connections that are
> > coming and going can't be named, but instead must each be given an
> > auto-generated UUID, they become very difficult to tell apart. If one were
> > a mere human working in the Broker's Management console, I would dare to
> > say it is impossible.
> >
> > I hope that makes sense. And in our case, it's a bit more complicated
> > because some services run on the same hosts (to save money), and when a
> > host scales, those services scale together.
> >
> > And back to what I originally was trying to convey in my first email to the
> > group:
> >
> > When creating Shared Consumers with our own unique Client IDs via the Uri
> > nms.clientId parameter, each Shared Subscriber receives all messages from
> > the topic, just like a regular subscriber (e.g.,
> > session.CreateConsumer(topic) ).
> >
> > To us, this does not make sense. Why would the Shared Subscribers (e.g.,
> > session.CreateSharedConsumer(topic, subscriptionName)) each receive all
> > messages when they have an explicitly set unique Client ID and a common
> > Subscription Name, but if you don't set the Client ID, it works as it
> > should, even though a unique Client ID is auto-generated for the
> > connection? (That's a rhetorical question.)
> >
> > This has to be a bug. And if it is by design, it should be changed. Well,
> > that is my two cents anyway.
> >
> > Thanks
> >
> > John
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > > Hope that helps!
> > >
> > >
> > > Justin
> > >
> > > On Thu, Mar 12, 2026 at 9:09 PM John <jk...@gmail.com> wrote:
> > > >
> > > > Hi Tim,
> > > >
> > > > I'm writing back again to talk about this issue more.
> > > >
> > > > Per our prior conversation, we've confirmed that, with Artemis (not
> > > > ActiveMQ) for Shared Consumers, using a single connection and setting the
> > > > nms.clientId parameter in the URI, any Shared Consumer created after the
> > > > first one throws an exception ("The key already existed in the
> > > > dictionary"). This same exception is thrown under the same circumstances
> > > > when the Client ID is not on the URI and is instead generated by the
> > > > library.
> > > >
> > > > And anyway, even if it would let us, using a single connection would not
> > > > work for us. This is because we have several services that subscribe to a
> > > > topic. One of the services takes a bit of time to process the messages
> > > from
> > > > the topic. For this particular service, we want to scale out to
> > > distribute
> > > > the message workload. And, technically, we want this ability for each
> > > > service. Also, using a queue for this service is not ideal as it defeats
> > > > the purpose of having a topic.
> > > >
> > > > Also, in our examination, the Client ID does not appear to be a shared
> > > > namespace, per se, as discussed earlier. Or, to clarify further, if the
> > > > Client ID is not assigned to the connections via nms.clientId, the
> > > > library-generated Client IDs are unique for each Shared Consumer's
> > > > connection and have the following format: "ID:HOSTNAME:UUID:N", where
> > > UUID
> > > > is unique for each connection.
> > > > This is odd regarding the earlier discussion, since the generated Client
> > > > IDs are unique. Why would our unique Client ID via nms.clientId be
> > > treated
> > > > any differently?
> > > >
> > > > Nevertheless, as far as we can tell, the only way Shared Consumers work
> > > > correctly is without setting our own Client IDs. But it would be
> > > > advantageous for us to use our own Client IDs, and it seems we should be
> > > > able to do so. And if so, we are back to the idea that this is a bug.
> > > >
> > > > Please let me know what your thoughts are.
> > > >
> > > > Thanks
> > > >
> > > > John
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > > On Tue, Mar 10, 2026 at 9:48 PM John <jk...@gmail.com> wrote:
> > > >
> > > > > Thank you for the explanation. I better understand now. And I think
> > > > > switching to regular consumers will probably work.
> > > > >
> > > > > Thanks again.
> > > > >
> > > > > On Tue, Mar 10, 2026 at 7:53 PM Timothy Bish <ta...@gmail.com>
> > > wrote:
> > > > >
> > > > >> 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 <ta...@gmail.com>
> > > > >> 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 <tabish121@gmail.com
> > > >
> > > > >> >> 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 <
> > > tabish121@gmail.com>
> > > > >> >> 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: users-unsubscribe@activemq.apache.org
> > > > >> >>>>>> For additional commands, e-mail:
> > > users-help@activemq.apache.org
> > > > >> >>>>>> For further information, visit:
> > > > >> https://activemq.apache.org/contact
> > > > >> >>>>>>
> > > > >> >>>>>>
> > > > >> >>>>>>
> > > > >> >>>> --
> > > > >> >>>> Tim Bish
> > > > >> >>>>
> > > > >> >>>>
> > > > >> >>>>
> > > ---------------------------------------------------------------------
> > > > >> >>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > > >> >>>> For additional commands, e-mail: users-help@activemq.apache.org
> > > > >> >>>> For further information, visit:
> > > https://activemq.apache.org/contact
> > > > >> >>>>
> > > > >> >>>>
> > > > >> >>>
> > > ---------------------------------------------------------------------
> > > > >> >>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > > >> >>> For additional commands, e-mail: users-help@activemq.apache.org
> > > > >> >>> For further information, visit:
> > > https://activemq.apache.org/contact
> > > > >> >>>
> > > > >> >>>
> > > > >> >> --
> > > > >> >> Tim Bish
> > > > >> >>
> > > > >> >>
> > > > >> >>
> > > ---------------------------------------------------------------------
> > > > >> >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > > >> >> For additional commands, e-mail: users-help@activemq.apache.org
> > > > >> >> For further information, visit:
> > > https://activemq.apache.org/contact
> > > > >> >>
> > > > >> >>
> > > > >> >>
> > > > >>
> > > > >> --
> > > > >> Tim Bish
> > > > >>
> > > > >>
> > > > >> ---------------------------------------------------------------------
> > > > >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > > >> For additional commands, e-mail: users-help@activemq.apache.org
> > > > >> For further information, visit: https://activemq.apache.org/contact
> > > > >>
> > > > >>
> > > > >>
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > For additional commands, e-mail: users-help@activemq.apache.org
> > > For further information, visit: https://activemq.apache.org/contact
> > >
> > >
> > >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> For additional commands, e-mail: users-help@activemq.apache.org
> For further information, visit: https://activemq.apache.org/contact
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
For additional commands, e-mail: users-help@activemq.apache.org
For further information, visit: https://activemq.apache.org/contact
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by Robbie Gemmell <ro...@gmail.com>.
The only bit which sounds like it may be a bug in the NMS client is if
you can't create multiple consumers on a shared subscription on the
same connection in a situation you actually should be able to. That
doesnt actually seem to be your main complaint though, so I'll
concentrate on your other thoughts that different connections each
with distinct ClientIDs explicitly set, getting the same messages,
whilst using a shared subscriber with the same shared subscription
name, would be a bug. It is not.
This is required JMS spec-defined behaviour from 2013 [and before]
with the release of JMS 2.0 API specification when shared
subscriptions were added, along with the ability to not actually set a
ClientID on a Connection and yet still use shared [durable]
subscriptions.
The spec requires that a shared subscription on a Connection with a
ClientID specified behaves one way, giving totally separate
ClientID-scoped namespaces for durable and non-durable named shared
subscriptions, and further that there is only a single joined
subscription namespace for both the shared durable and
previously-existing JMS 1 non-shared durable named subscriptions that
were already ClientID-scoped since 1998. The spec also requires that
shared subscriptions on a Connection without a ClientID specified
behave in a completely different way, with each of durable and
non-durable shared subscriptions being in separate namespaces
(distinct from both each other, and from those on Connections with a
ClientID specified) with a given named subscription of a given type
then shareable between all such Connections similarly without any
ClientID specified. For completeness, you can't have a non-shared
durable subscription on a Connection without a ClientID specified.
If you do specify a ClientID, the spec thus inherently requires that
you can then only have other shared consumers for that ClientID-scoped
shared subscription on that very same Connection, since only one
Connection can use a ClientID at a given time and the subscription is
scoped to that ClientID, meaning no other Connection can share that
subscription at the same time, end of story. Different Connections
with a distinct specified ClientID can each have their own similar
subscriptions with the same subscription name, but that is a totally
separate subscription scoped to their ClientID, and they thus receive
their own copy of the messages like any distinct subscription should.
If that doesnt meet your needs because e.g. you want to share a single
subscription across multiple different Connections, then you would
need to not set a ClientID on your Connections in which case all such
Connections without ClientID can share that distinct
not-ClientID-scoped named subscription since they are then all
accessing the same subscription, or else you would need to use a
regular Queue with competing consumers (this behaving the same
regardless of the ClientID being explicitly specified or not since its
not a topic subscription), as has been explained before.
The ClientID if specified is conveyed on the wire in the container-id
field which must have a value, so the client generates a value for
this if a ClientID was not explicitly specified. It is known whether a
ClientID has been explicitly specified or not, and then in turn it is
known when a shared[/non-shared durable] subscription is being created
whether a ClientID was specified or not, and a different thing is done
in these cases resulting in the different required behaviours detailed
by the JMS specification and outlined above and previously in the
thread. The NMS behaviour is based on this JMS behaviour.
I know that in Qpid JMS we allow defining a 'ClientIDPrefix' to be
used within the auto-generated values if you dont actually specify a
ClientID. I dont know for sure if that functionality was copied in the
NMS AMQP client but I would guess it was. If so perhaps you can use
that to help discriminate between different connections if your main
concern is harder identification of things using a generated
container-id value that's being displayed as a ClientID in the
console.
In terms of the overall behaviour you can avail yourself of the
formerly-JMS / now Jakarta Messaging specification at:
https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/package-summary
Of particular relation to the discussion would be the 8 shared and
non-shared subscription methods that cover all the behaviour as it has
already been explained:
https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createDurableConsumer(jakarta.jms.Topic,java.lang.String)
https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createDurableConsumer(jakarta.jms.Topic,java.lang.String,java.lang.String,boolean)
https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createDurableSubscriber(jakarta.jms.Topic,java.lang.String)
https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createDurableSubscriber(jakarta.jms.Topic,java.lang.String,java.lang.String,boolean)
https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createSharedConsumer(jakarta.jms.Topic,java.lang.String)
https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createSharedConsumer(jakarta.jms.Topic,java.lang.String,java.lang.String)
https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createSharedDurableConsumer(jakarta.jms.Topic,java.lang.String)
https://jakarta.ee/specifications/messaging/3.1/apidocs/jakarta.messaging/jakarta/jms/session#createSharedDurableConsumer(jakarta.jms.Topic,java.lang.String,java.lang.String)
Robbie
On Sat, 14 Mar 2026 at 05:48, John <jk...@gmail.com> wrote:
>
> On Thu, Mar 12, 2026 at 7:47 PM Justin Bertram <jb...@apache.org> wrote:
>
> > If I may interject...
> >
> > I'm not super familiar with the NMS client you're using, but my
> > understanding is that it should essentially act like a traditional JMS
> > client for this use-case. Assuming that's true, I think everything
> > you're seeing is the expected behavior.
> >
> > Here are a few things to keep in mind (distilling what Tim already said):
> >
> > 1) Any client wishing to connect to the broker with a client ID must
> > ensure that ID is unique among all connected clients. Clients
> > attempting to connect using a client ID already in use will be
> > rejected.
> >
>
> I agree with this. Where a client is considered a connection. As it is our
> observation that each connection is either given a unique Client ID when
> not explicitly set, or if the Client ID is assigned via the nms.clientId
> parameter, then it must be unique; otherwise, an exception is thrown.
>
>
> > 2) If set, the client ID will become part of any shared subscription
> > created. Receiving messages from that shared subscription requires the
> > same client ID.
> >
>
> This does not track with what we are seeing. So, I almost think that the
> terminology in NMS differs from that in JMS. Almost, thinking that possibly
> "Shared Subscriptions" or "Client ID" for the observed behaviors for NMS
> doesn't mean the same as in JMS.
>
> I say observed behaviors, because we have not found much documentation on
> NMS, and so here is what we have figured out in NMS:
>
> The Client ID is always set. Either automatically when creating the
> connection or explicitly via the NMS.clientId Uri parameter. In either
> case, the Client ID will/must be unique.
>
> When creating a Shared Subscriber (e.g.,
> session.CreateSharedConsumer(topic, subscriptionName)), messages from that
> topic are supposed to be distributed among the Shared Subscribers. (They
> don't each receive all the messages. The messages are divided among the
> Shared Subscribers.)
>
> And to create a Shared Subscriber, one must have a unique Client ID
> (whether set implicitly or explicitly) and a common Subscription Name.
>
> And for (#2), to make sense (somewhat) in NMS, instead of "Client ID," as
> stated, maybe it should read "Subscription Name". As I already stated in
> NMS, the Client ID is always set, no matter what.
>
> And in NMS, the only way any type of subscriber would have the same Client
> ID is to be on the same connection. But if one were to try to create more
> than one Shared Subscriber on a connection (whether the Client ID is
> implicitly or explicitly set), an exception is thrown: "The key already
> existed in the dictionary."
>
>
> > 3) The client ID may be null when creating a shared subscription.
> >
>
> With NMS, if a Client ID is not explicitly assigned, then it is
> automatically generated for the connection. So, this isn't true in NMS.
> There will always be a Client ID.
>
> Now, as I mentioned above (#2), in NMS, if the "Client ID" was meant to
> read as "Subscription Name", then yes, the Subscription Name can be null
> when creating Shared Subscribers. However, they do not behave like Shared
> Subscribers, as each receives all messages for the topic, just like a
> regular subscriber (e.g., session.CreateConsumer(topic)), defeating the
> purpose of Shared Subscribers.
>
>
>
> > 4) If you want to share a subscription among several simultaneously
> > connected clients, do not set the client ID.
> >
> > The whole client ID + shared subscription combo just doesn't make a
> > lot of sense. Shared subscriptions were added to the JMS specification
> > years after client ID was established so not everything fits perfectly
> > conceptually. However, once you understand the basic rules it's pretty
> > straight-forward.
> >
> >
> Well, this is true. Not explicitly setting the Client ID and allowing the
> connection to generate its own unique Client ID allows for Shared Consumers
> to work correctly. But this is what I'm complaining about.
>
> And for some, sharing (dividing) messages on a topic makes sense.
> Let's walk through a use case:
> Let's say multiple "microservices" are subscribed to a topic, each handling
> the messages received on that topic. Then, let's say one of these services
> takes a long time to handle messages from the topic. Then, for this one
> service, it makes sense to scale out, meaning running more than one
> instance of it. Then, for this one service, it would want the message
> divided among its instances, with each instance handling its share, thereby
> spreading the workload.
> Now, let's say many of the "microservices", each need to scale out to
> handle the workload generated by the many more messages on that topic
> during a large traffic spike. Each instance of each service needs to handle
> its share of messages, but overall, each service needs to receive all
> messages from the topic. Now, imagine these service instances are all
> coming and going as traffic ramps up and down. And then say someone (or
> another service) has the task of monitoring or troubleshooting these
> connections and subscribers, but since all these connections that are
> coming and going can't be named, but instead must each be given an
> auto-generated UUID, they become very difficult to tell apart. If one were
> a mere human working in the Broker's Management console, I would dare to
> say it is impossible.
>
> I hope that makes sense. And in our case, it's a bit more complicated
> because some services run on the same hosts (to save money), and when a
> host scales, those services scale together.
>
> And back to what I originally was trying to convey in my first email to the
> group:
>
> When creating Shared Consumers with our own unique Client IDs via the Uri
> nms.clientId parameter, each Shared Subscriber receives all messages from
> the topic, just like a regular subscriber (e.g.,
> session.CreateConsumer(topic) ).
>
> To us, this does not make sense. Why would the Shared Subscribers (e.g.,
> session.CreateSharedConsumer(topic, subscriptionName)) each receive all
> messages when they have an explicitly set unique Client ID and a common
> Subscription Name, but if you don't set the Client ID, it works as it
> should, even though a unique Client ID is auto-generated for the
> connection? (That's a rhetorical question.)
>
> This has to be a bug. And if it is by design, it should be changed. Well,
> that is my two cents anyway.
>
> Thanks
>
> John
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> > Hope that helps!
> >
> >
> > Justin
> >
> > On Thu, Mar 12, 2026 at 9:09 PM John <jk...@gmail.com> wrote:
> > >
> > > Hi Tim,
> > >
> > > I'm writing back again to talk about this issue more.
> > >
> > > Per our prior conversation, we've confirmed that, with Artemis (not
> > > ActiveMQ) for Shared Consumers, using a single connection and setting the
> > > nms.clientId parameter in the URI, any Shared Consumer created after the
> > > first one throws an exception ("The key already existed in the
> > > dictionary"). This same exception is thrown under the same circumstances
> > > when the Client ID is not on the URI and is instead generated by the
> > > library.
> > >
> > > And anyway, even if it would let us, using a single connection would not
> > > work for us. This is because we have several services that subscribe to a
> > > topic. One of the services takes a bit of time to process the messages
> > from
> > > the topic. For this particular service, we want to scale out to
> > distribute
> > > the message workload. And, technically, we want this ability for each
> > > service. Also, using a queue for this service is not ideal as it defeats
> > > the purpose of having a topic.
> > >
> > > Also, in our examination, the Client ID does not appear to be a shared
> > > namespace, per se, as discussed earlier. Or, to clarify further, if the
> > > Client ID is not assigned to the connections via nms.clientId, the
> > > library-generated Client IDs are unique for each Shared Consumer's
> > > connection and have the following format: "ID:HOSTNAME:UUID:N", where
> > UUID
> > > is unique for each connection.
> > > This is odd regarding the earlier discussion, since the generated Client
> > > IDs are unique. Why would our unique Client ID via nms.clientId be
> > treated
> > > any differently?
> > >
> > > Nevertheless, as far as we can tell, the only way Shared Consumers work
> > > correctly is without setting our own Client IDs. But it would be
> > > advantageous for us to use our own Client IDs, and it seems we should be
> > > able to do so. And if so, we are back to the idea that this is a bug.
> > >
> > > Please let me know what your thoughts are.
> > >
> > > Thanks
> > >
> > > John
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > > On Tue, Mar 10, 2026 at 9:48 PM John <jk...@gmail.com> wrote:
> > >
> > > > Thank you for the explanation. I better understand now. And I think
> > > > switching to regular consumers will probably work.
> > > >
> > > > Thanks again.
> > > >
> > > > On Tue, Mar 10, 2026 at 7:53 PM Timothy Bish <ta...@gmail.com>
> > wrote:
> > > >
> > > >> 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 <ta...@gmail.com>
> > > >> 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 <tabish121@gmail.com
> > >
> > > >> >> 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 <
> > tabish121@gmail.com>
> > > >> >> 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: users-unsubscribe@activemq.apache.org
> > > >> >>>>>> For additional commands, e-mail:
> > users-help@activemq.apache.org
> > > >> >>>>>> For further information, visit:
> > > >> https://activemq.apache.org/contact
> > > >> >>>>>>
> > > >> >>>>>>
> > > >> >>>>>>
> > > >> >>>> --
> > > >> >>>> Tim Bish
> > > >> >>>>
> > > >> >>>>
> > > >> >>>>
> > ---------------------------------------------------------------------
> > > >> >>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > >> >>>> For additional commands, e-mail: users-help@activemq.apache.org
> > > >> >>>> For further information, visit:
> > https://activemq.apache.org/contact
> > > >> >>>>
> > > >> >>>>
> > > >> >>>
> > ---------------------------------------------------------------------
> > > >> >>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > >> >>> For additional commands, e-mail: users-help@activemq.apache.org
> > > >> >>> For further information, visit:
> > https://activemq.apache.org/contact
> > > >> >>>
> > > >> >>>
> > > >> >> --
> > > >> >> Tim Bish
> > > >> >>
> > > >> >>
> > > >> >>
> > ---------------------------------------------------------------------
> > > >> >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > >> >> For additional commands, e-mail: users-help@activemq.apache.org
> > > >> >> For further information, visit:
> > https://activemq.apache.org/contact
> > > >> >>
> > > >> >>
> > > >> >>
> > > >>
> > > >> --
> > > >> Tim Bish
> > > >>
> > > >>
> > > >> ---------------------------------------------------------------------
> > > >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > > >> For additional commands, e-mail: users-help@activemq.apache.org
> > > >> For further information, visit: https://activemq.apache.org/contact
> > > >>
> > > >>
> > > >>
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > For additional commands, e-mail: users-help@activemq.apache.org
> > For further information, visit: https://activemq.apache.org/contact
> >
> >
> >
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
For additional commands, e-mail: users-help@activemq.apache.org
For further information, visit: https://activemq.apache.org/contact
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by John <jk...@gmail.com>.
On Thu, Mar 12, 2026 at 7:47 PM Justin Bertram <jb...@apache.org> wrote:
> If I may interject...
>
> I'm not super familiar with the NMS client you're using, but my
> understanding is that it should essentially act like a traditional JMS
> client for this use-case. Assuming that's true, I think everything
> you're seeing is the expected behavior.
>
> Here are a few things to keep in mind (distilling what Tim already said):
>
> 1) Any client wishing to connect to the broker with a client ID must
> ensure that ID is unique among all connected clients. Clients
> attempting to connect using a client ID already in use will be
> rejected.
>
I agree with this. Where a client is considered a connection. As it is our
observation that each connection is either given a unique Client ID when
not explicitly set, or if the Client ID is assigned via the nms.clientId
parameter, then it must be unique; otherwise, an exception is thrown.
> 2) If set, the client ID will become part of any shared subscription
> created. Receiving messages from that shared subscription requires the
> same client ID.
>
This does not track with what we are seeing. So, I almost think that the
terminology in NMS differs from that in JMS. Almost, thinking that possibly
"Shared Subscriptions" or "Client ID" for the observed behaviors for NMS
doesn't mean the same as in JMS.
I say observed behaviors, because we have not found much documentation on
NMS, and so here is what we have figured out in NMS:
The Client ID is always set. Either automatically when creating the
connection or explicitly via the NMS.clientId Uri parameter. In either
case, the Client ID will/must be unique.
When creating a Shared Subscriber (e.g.,
session.CreateSharedConsumer(topic, subscriptionName)), messages from that
topic are supposed to be distributed among the Shared Subscribers. (They
don't each receive all the messages. The messages are divided among the
Shared Subscribers.)
And to create a Shared Subscriber, one must have a unique Client ID
(whether set implicitly or explicitly) and a common Subscription Name.
And for (#2), to make sense (somewhat) in NMS, instead of "Client ID," as
stated, maybe it should read "Subscription Name". As I already stated in
NMS, the Client ID is always set, no matter what.
And in NMS, the only way any type of subscriber would have the same Client
ID is to be on the same connection. But if one were to try to create more
than one Shared Subscriber on a connection (whether the Client ID is
implicitly or explicitly set), an exception is thrown: "The key already
existed in the dictionary."
> 3) The client ID may be null when creating a shared subscription.
>
With NMS, if a Client ID is not explicitly assigned, then it is
automatically generated for the connection. So, this isn't true in NMS.
There will always be a Client ID.
Now, as I mentioned above (#2), in NMS, if the "Client ID" was meant to
read as "Subscription Name", then yes, the Subscription Name can be null
when creating Shared Subscribers. However, they do not behave like Shared
Subscribers, as each receives all messages for the topic, just like a
regular subscriber (e.g., session.CreateConsumer(topic)), defeating the
purpose of Shared Subscribers.
> 4) If you want to share a subscription among several simultaneously
> connected clients, do not set the client ID.
>
> The whole client ID + shared subscription combo just doesn't make a
> lot of sense. Shared subscriptions were added to the JMS specification
> years after client ID was established so not everything fits perfectly
> conceptually. However, once you understand the basic rules it's pretty
> straight-forward.
>
>
Well, this is true. Not explicitly setting the Client ID and allowing the
connection to generate its own unique Client ID allows for Shared Consumers
to work correctly. But this is what I'm complaining about.
And for some, sharing (dividing) messages on a topic makes sense.
Let's walk through a use case:
Let's say multiple "microservices" are subscribed to a topic, each handling
the messages received on that topic. Then, let's say one of these services
takes a long time to handle messages from the topic. Then, for this one
service, it makes sense to scale out, meaning running more than one
instance of it. Then, for this one service, it would want the message
divided among its instances, with each instance handling its share, thereby
spreading the workload.
Now, let's say many of the "microservices", each need to scale out to
handle the workload generated by the many more messages on that topic
during a large traffic spike. Each instance of each service needs to handle
its share of messages, but overall, each service needs to receive all
messages from the topic. Now, imagine these service instances are all
coming and going as traffic ramps up and down. And then say someone (or
another service) has the task of monitoring or troubleshooting these
connections and subscribers, but since all these connections that are
coming and going can't be named, but instead must each be given an
auto-generated UUID, they become very difficult to tell apart. If one were
a mere human working in the Broker's Management console, I would dare to
say it is impossible.
I hope that makes sense. And in our case, it's a bit more complicated
because some services run on the same hosts (to save money), and when a
host scales, those services scale together.
And back to what I originally was trying to convey in my first email to the
group:
When creating Shared Consumers with our own unique Client IDs via the Uri
nms.clientId parameter, each Shared Subscriber receives all messages from
the topic, just like a regular subscriber (e.g.,
session.CreateConsumer(topic) ).
To us, this does not make sense. Why would the Shared Subscribers (e.g.,
session.CreateSharedConsumer(topic, subscriptionName)) each receive all
messages when they have an explicitly set unique Client ID and a common
Subscription Name, but if you don't set the Client ID, it works as it
should, even though a unique Client ID is auto-generated for the
connection? (That's a rhetorical question.)
This has to be a bug. And if it is by design, it should be changed. Well,
that is my two cents anyway.
Thanks
John
> Hope that helps!
>
>
> Justin
>
> On Thu, Mar 12, 2026 at 9:09 PM John <jk...@gmail.com> wrote:
> >
> > Hi Tim,
> >
> > I'm writing back again to talk about this issue more.
> >
> > Per our prior conversation, we've confirmed that, with Artemis (not
> > ActiveMQ) for Shared Consumers, using a single connection and setting the
> > nms.clientId parameter in the URI, any Shared Consumer created after the
> > first one throws an exception ("The key already existed in the
> > dictionary"). This same exception is thrown under the same circumstances
> > when the Client ID is not on the URI and is instead generated by the
> > library.
> >
> > And anyway, even if it would let us, using a single connection would not
> > work for us. This is because we have several services that subscribe to a
> > topic. One of the services takes a bit of time to process the messages
> from
> > the topic. For this particular service, we want to scale out to
> distribute
> > the message workload. And, technically, we want this ability for each
> > service. Also, using a queue for this service is not ideal as it defeats
> > the purpose of having a topic.
> >
> > Also, in our examination, the Client ID does not appear to be a shared
> > namespace, per se, as discussed earlier. Or, to clarify further, if the
> > Client ID is not assigned to the connections via nms.clientId, the
> > library-generated Client IDs are unique for each Shared Consumer's
> > connection and have the following format: "ID:HOSTNAME:UUID:N", where
> UUID
> > is unique for each connection.
> > This is odd regarding the earlier discussion, since the generated Client
> > IDs are unique. Why would our unique Client ID via nms.clientId be
> treated
> > any differently?
> >
> > Nevertheless, as far as we can tell, the only way Shared Consumers work
> > correctly is without setting our own Client IDs. But it would be
> > advantageous for us to use our own Client IDs, and it seems we should be
> > able to do so. And if so, we are back to the idea that this is a bug.
> >
> > Please let me know what your thoughts are.
> >
> > Thanks
> >
> > John
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > On Tue, Mar 10, 2026 at 9:48 PM John <jk...@gmail.com> wrote:
> >
> > > Thank you for the explanation. I better understand now. And I think
> > > switching to regular consumers will probably work.
> > >
> > > Thanks again.
> > >
> > > On Tue, Mar 10, 2026 at 7:53 PM Timothy Bish <ta...@gmail.com>
> wrote:
> > >
> > >> 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 <ta...@gmail.com>
> > >> 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 <tabish121@gmail.com
> >
> > >> >> 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 <
> tabish121@gmail.com>
> > >> >> 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: users-unsubscribe@activemq.apache.org
> > >> >>>>>> For additional commands, e-mail:
> users-help@activemq.apache.org
> > >> >>>>>> For further information, visit:
> > >> https://activemq.apache.org/contact
> > >> >>>>>>
> > >> >>>>>>
> > >> >>>>>>
> > >> >>>> --
> > >> >>>> Tim Bish
> > >> >>>>
> > >> >>>>
> > >> >>>>
> ---------------------------------------------------------------------
> > >> >>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > >> >>>> For additional commands, e-mail: users-help@activemq.apache.org
> > >> >>>> For further information, visit:
> https://activemq.apache.org/contact
> > >> >>>>
> > >> >>>>
> > >> >>>
> ---------------------------------------------------------------------
> > >> >>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > >> >>> For additional commands, e-mail: users-help@activemq.apache.org
> > >> >>> For further information, visit:
> https://activemq.apache.org/contact
> > >> >>>
> > >> >>>
> > >> >> --
> > >> >> Tim Bish
> > >> >>
> > >> >>
> > >> >>
> ---------------------------------------------------------------------
> > >> >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > >> >> For additional commands, e-mail: users-help@activemq.apache.org
> > >> >> For further information, visit:
> https://activemq.apache.org/contact
> > >> >>
> > >> >>
> > >> >>
> > >>
> > >> --
> > >> Tim Bish
> > >>
> > >>
> > >> ---------------------------------------------------------------------
> > >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > >> For additional commands, e-mail: users-help@activemq.apache.org
> > >> For further information, visit: https://activemq.apache.org/contact
> > >>
> > >>
> > >>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> For additional commands, e-mail: users-help@activemq.apache.org
> For further information, visit: https://activemq.apache.org/contact
>
>
>
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by Justin Bertram <jb...@apache.org>.
If I may interject...
I'm not super familiar with the NMS client you're using, but my
understanding is that it should essentially act like a traditional JMS
client for this use-case. Assuming that's true, I think everything
you're seeing is the expected behavior.
Here are a few things to keep in mind (distilling what Tim already said):
1) Any client wishing to connect to the broker with a client ID must
ensure that ID is unique among all connected clients. Clients
attempting to connect using a client ID already in use will be
rejected.
2) If set, the client ID will become part of any shared subscription
created. Receiving messages from that shared subscription requires the
same client ID.
3) The client ID may be null when creating a shared subscription.
4) If you want to share a subscription among several simultaneously
connected clients, do not set the client ID.
The whole client ID + shared subscription combo just doesn't make a
lot of sense. Shared subscriptions were added to the JMS specification
years after client ID was established so not everything fits perfectly
conceptually. However, once you understand the basic rules it's pretty
straight-forward.
Hope that helps!
Justin
On Thu, Mar 12, 2026 at 9:09 PM John <jk...@gmail.com> wrote:
>
> Hi Tim,
>
> I'm writing back again to talk about this issue more.
>
> Per our prior conversation, we've confirmed that, with Artemis (not
> ActiveMQ) for Shared Consumers, using a single connection and setting the
> nms.clientId parameter in the URI, any Shared Consumer created after the
> first one throws an exception ("The key already existed in the
> dictionary"). This same exception is thrown under the same circumstances
> when the Client ID is not on the URI and is instead generated by the
> library.
>
> And anyway, even if it would let us, using a single connection would not
> work for us. This is because we have several services that subscribe to a
> topic. One of the services takes a bit of time to process the messages from
> the topic. For this particular service, we want to scale out to distribute
> the message workload. And, technically, we want this ability for each
> service. Also, using a queue for this service is not ideal as it defeats
> the purpose of having a topic.
>
> Also, in our examination, the Client ID does not appear to be a shared
> namespace, per se, as discussed earlier. Or, to clarify further, if the
> Client ID is not assigned to the connections via nms.clientId, the
> library-generated Client IDs are unique for each Shared Consumer's
> connection and have the following format: "ID:HOSTNAME:UUID:N", where UUID
> is unique for each connection.
> This is odd regarding the earlier discussion, since the generated Client
> IDs are unique. Why would our unique Client ID via nms.clientId be treated
> any differently?
>
> Nevertheless, as far as we can tell, the only way Shared Consumers work
> correctly is without setting our own Client IDs. But it would be
> advantageous for us to use our own Client IDs, and it seems we should be
> able to do so. And if so, we are back to the idea that this is a bug.
>
> Please let me know what your thoughts are.
>
> Thanks
>
> John
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> On Tue, Mar 10, 2026 at 9:48 PM John <jk...@gmail.com> wrote:
>
> > Thank you for the explanation. I better understand now. And I think
> > switching to regular consumers will probably work.
> >
> > Thanks again.
> >
> > On Tue, Mar 10, 2026 at 7:53 PM Timothy Bish <ta...@gmail.com> wrote:
> >
> >> 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 <ta...@gmail.com>
> >> 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 <ta...@gmail.com>
> >> >> 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 <ta...@gmail.com>
> >> >> 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: users-unsubscribe@activemq.apache.org
> >> >>>>>> For additional commands, e-mail: users-help@activemq.apache.org
> >> >>>>>> For further information, visit:
> >> https://activemq.apache.org/contact
> >> >>>>>>
> >> >>>>>>
> >> >>>>>>
> >> >>>> --
> >> >>>> Tim Bish
> >> >>>>
> >> >>>>
> >> >>>> ---------------------------------------------------------------------
> >> >>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> >> >>>> For additional commands, e-mail: users-help@activemq.apache.org
> >> >>>> For further information, visit: https://activemq.apache.org/contact
> >> >>>>
> >> >>>>
> >> >>> ---------------------------------------------------------------------
> >> >>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> >> >>> For additional commands, e-mail: users-help@activemq.apache.org
> >> >>> For further information, visit: https://activemq.apache.org/contact
> >> >>>
> >> >>>
> >> >> --
> >> >> Tim Bish
> >> >>
> >> >>
> >> >> ---------------------------------------------------------------------
> >> >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> >> >> For additional commands, e-mail: users-help@activemq.apache.org
> >> >> For further information, visit: https://activemq.apache.org/contact
> >> >>
> >> >>
> >> >>
> >>
> >> --
> >> Tim Bish
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> >> For additional commands, e-mail: users-help@activemq.apache.org
> >> For further information, visit: https://activemq.apache.org/contact
> >>
> >>
> >>
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
For additional commands, e-mail: users-help@activemq.apache.org
For further information, visit: https://activemq.apache.org/contact
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by Timothy Bish <ta...@gmail.com>.
On 3/12/26 22:08, John wrote:
> Hi Tim,
>
> I'm writing back again to talk about this issue more.
>
> Per our prior conversation, we've confirmed that, with Artemis (not
> ActiveMQ) for Shared Consumers, using a single connection and setting the
> nms.clientId parameter in the URI, any Shared Consumer created after the
> first one throws an exception ("The key already existed in the
> dictionary"). This same exception is thrown under the same circumstances
> when the Client ID is not on the URI and is instead generated by the
> library.
I'm not 100% clear on what you did but this sounds like a bug in
NMS.AMQP if the application set a client ID on a single connection and
then tried to create multiple consumers on that **same** connection for
the shared subscription that ought to work. I don't know much about the
NMS client so I can't really help on that front. You could conform this
works by trying the same thing with Qpid JMS and it would work, I just
did it locally and had no issue.
>
> And anyway, even if it would let us, using a single connection would not
> work for us. This is because we have several services that subscribe to a
> topic. One of the services takes a bit of time to process the messages from
> the topic. For this particular service, we want to scale out to distribute
> the message workload. And, technically, we want this ability for each
> service. Also, using a queue for this service is not ideal as it defeats
> the purpose of having a topic.
I'm not clear on your use case so can't fully say what will work for you
but if you are intending to use shared subscriptions so that any given
message sent to a topic is only sent to a single client for processing
via a shared subscription then those clients are treating it as a Queue,
that's what Queues do. Internally the broker implements shared
subscriptions as Queues attached to an multicast address.
>
> Also, in our examination, the Client ID does not appear to be a shared
> namespace, per se, as discussed earlier. Or, to clarify further, if the
> Client ID is not assigned to the connections via nms.clientId, the
> library-generated Client IDs are unique for each Shared Consumer's
> connection and have the following format: "ID:HOSTNAME:UUID:N", where UUID
> is unique for each connection.
> This is odd regarding the earlier discussion, since the generated Client
> IDs are unique. Why would our unique Client ID via nms.clientId be treated
> any differently?
You can set unique client IDs for each connection, but you cannot set a
single unique client ID for all connections, JMS prohibits that. The
client ID generated by NMS.AMQP looks to be unique to each connection
which is fine, and is distinct from how the client deals with shared
subscriptions at the implementation where it uses its knowledge of
whether you've set a client ID yourself or its using an internally
generated one just for the sake of allowing the remote to have some
identifying data about an incoming connection. When it creates a shared
or durable shared subscriptions it must check if you've explicitly set a
client ID and use that knowledge to tag the AMQP link with properties
that indicate if the subscription is globally shared (no-client ID) or
privately shared (explicit client ID).
>
> Nevertheless, as far as we can tell, the only way Shared Consumers work
> correctly is without setting our own Client IDs. But it would be
> advantageous for us to use our own Client IDs, and it seems we should be
> able to do so. And if so, we are back to the idea that this is a bug.
You are confusing how you would like it to work with how the JMS
specification says it must work which means you likely need to review
the JMS specification and maybe rethink or reshape your solution in
terms of what is possible within the bounds of the specification defined
behavior. It does sound like you might have run into a bug in NMS.AMQP
in terms of its own internal handling of shared subs which you could
report but that won't help you with the main issue at hand as you've
already noted.
>
> Please let me know what your thoughts are.
>
> Thanks
>
> John
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> On Tue, Mar 10, 2026 at 9:48 PM John <jk...@gmail.com> wrote:
>
>> Thank you for the explanation. I better understand now. And I think
>> switching to regular consumers will probably work.
>>
>> Thanks again.
>>
>> On Tue, Mar 10, 2026 at 7:53 PM Timothy Bish <ta...@gmail.com> wrote:
>>
>>> 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 <ta...@gmail.com>
>>> 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 <ta...@gmail.com>
>>>>> 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 <ta...@gmail.com>
>>>>> 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: users-unsubscribe@activemq.apache.org
>>>>>>>>> For additional commands, e-mail: users-help@activemq.apache.org
>>>>>>>>> For further information, visit:
>>> https://activemq.apache.org/contact
>>>>>>>>>
>>>>>>>>>
>>>>>>> --
>>>>>>> Tim Bish
>>>>>>>
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
>>>>>>> For additional commands, e-mail: users-help@activemq.apache.org
>>>>>>> For further information, visit: https://activemq.apache.org/contact
>>>>>>>
>>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
>>>>>> For additional commands, e-mail: users-help@activemq.apache.org
>>>>>> For further information, visit: https://activemq.apache.org/contact
>>>>>>
>>>>>>
>>>>> --
>>>>> Tim Bish
>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
>>>>> For additional commands, e-mail: users-help@activemq.apache.org
>>>>> For further information, visit: https://activemq.apache.org/contact
>>>>>
>>>>>
>>>>>
>>> --
>>> Tim Bish
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
>>> For additional commands, e-mail: users-help@activemq.apache.org
>>> For further information, visit: https://activemq.apache.org/contact
>>>
>>>
>>>
--
Tim Bish
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
For additional commands, e-mail: users-help@activemq.apache.org
For further information, visit: https://activemq.apache.org/contact
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by John <jk...@gmail.com>.
Hi Tim,
I'm writing back again to talk about this issue more.
Per our prior conversation, we've confirmed that, with Artemis (not
ActiveMQ) for Shared Consumers, using a single connection and setting the
nms.clientId parameter in the URI, any Shared Consumer created after the
first one throws an exception ("The key already existed in the
dictionary"). This same exception is thrown under the same circumstances
when the Client ID is not on the URI and is instead generated by the
library.
And anyway, even if it would let us, using a single connection would not
work for us. This is because we have several services that subscribe to a
topic. One of the services takes a bit of time to process the messages from
the topic. For this particular service, we want to scale out to distribute
the message workload. And, technically, we want this ability for each
service. Also, using a queue for this service is not ideal as it defeats
the purpose of having a topic.
Also, in our examination, the Client ID does not appear to be a shared
namespace, per se, as discussed earlier. Or, to clarify further, if the
Client ID is not assigned to the connections via nms.clientId, the
library-generated Client IDs are unique for each Shared Consumer's
connection and have the following format: "ID:HOSTNAME:UUID:N", where UUID
is unique for each connection.
This is odd regarding the earlier discussion, since the generated Client
IDs are unique. Why would our unique Client ID via nms.clientId be treated
any differently?
Nevertheless, as far as we can tell, the only way Shared Consumers work
correctly is without setting our own Client IDs. But it would be
advantageous for us to use our own Client IDs, and it seems we should be
able to do so. And if so, we are back to the idea that this is a bug.
Please let me know what your thoughts are.
Thanks
John
On Tue, Mar 10, 2026 at 9:48 PM John <jk...@gmail.com> wrote:
> Thank you for the explanation. I better understand now. And I think
> switching to regular consumers will probably work.
>
> Thanks again.
>
> On Tue, Mar 10, 2026 at 7:53 PM Timothy Bish <ta...@gmail.com> wrote:
>
>> 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 <ta...@gmail.com>
>> 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 <ta...@gmail.com>
>> >> 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 <ta...@gmail.com>
>> >> 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: users-unsubscribe@activemq.apache.org
>> >>>>>> For additional commands, e-mail: users-help@activemq.apache.org
>> >>>>>> For further information, visit:
>> https://activemq.apache.org/contact
>> >>>>>>
>> >>>>>>
>> >>>>>>
>> >>>> --
>> >>>> Tim Bish
>> >>>>
>> >>>>
>> >>>> ---------------------------------------------------------------------
>> >>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
>> >>>> For additional commands, e-mail: users-help@activemq.apache.org
>> >>>> For further information, visit: https://activemq.apache.org/contact
>> >>>>
>> >>>>
>> >>> ---------------------------------------------------------------------
>> >>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
>> >>> For additional commands, e-mail: users-help@activemq.apache.org
>> >>> For further information, visit: https://activemq.apache.org/contact
>> >>>
>> >>>
>> >> --
>> >> Tim Bish
>> >>
>> >>
>> >> ---------------------------------------------------------------------
>> >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
>> >> For additional commands, e-mail: users-help@activemq.apache.org
>> >> For further information, visit: https://activemq.apache.org/contact
>> >>
>> >>
>> >>
>>
>> --
>> Tim Bish
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
>> For additional commands, e-mail: users-help@activemq.apache.org
>> For further information, visit: https://activemq.apache.org/contact
>>
>>
>>
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by John <jk...@gmail.com>.
Thank you for the explanation. I better understand now. And I think
switching to regular consumers will probably work.
Thanks again.
On Tue, Mar 10, 2026 at 7:53 PM Timothy Bish <ta...@gmail.com> wrote:
> 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 <ta...@gmail.com>
> 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 <ta...@gmail.com>
> >> 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 <ta...@gmail.com>
> >> 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: users-unsubscribe@activemq.apache.org
> >>>>>> For additional commands, e-mail: users-help@activemq.apache.org
> >>>>>> For further information, visit: https://activemq.apache.org/contact
> >>>>>>
> >>>>>>
> >>>>>>
> >>>> --
> >>>> Tim Bish
> >>>>
> >>>>
> >>>> ---------------------------------------------------------------------
> >>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> >>>> For additional commands, e-mail: users-help@activemq.apache.org
> >>>> For further information, visit: https://activemq.apache.org/contact
> >>>>
> >>>>
> >>> ---------------------------------------------------------------------
> >>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> >>> For additional commands, e-mail: users-help@activemq.apache.org
> >>> For further information, visit: https://activemq.apache.org/contact
> >>>
> >>>
> >> --
> >> Tim Bish
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> >> For additional commands, e-mail: users-help@activemq.apache.org
> >> For further information, visit: https://activemq.apache.org/contact
> >>
> >>
> >>
>
> --
> Tim Bish
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> For additional commands, e-mail: users-help@activemq.apache.org
> For further information, visit: https://activemq.apache.org/contact
>
>
>
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by Timothy Bish <ta...@gmail.com>.
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 <ta...@gmail.com> 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 <ta...@gmail.com>
>> 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 <ta...@gmail.com>
>> 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: users-unsubscribe@activemq.apache.org
>>>>>> For additional commands, e-mail: users-help@activemq.apache.org
>>>>>> For further information, visit: https://activemq.apache.org/contact
>>>>>>
>>>>>>
>>>>>>
>>>> --
>>>> Tim Bish
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
>>>> For additional commands, e-mail: users-help@activemq.apache.org
>>>> For further information, visit: https://activemq.apache.org/contact
>>>>
>>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
>>> For additional commands, e-mail: users-help@activemq.apache.org
>>> For further information, visit: https://activemq.apache.org/contact
>>>
>>>
>> --
>> Tim Bish
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
>> For additional commands, e-mail: users-help@activemq.apache.org
>> For further information, visit: https://activemq.apache.org/contact
>>
>>
>>
--
Tim Bish
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
For additional commands, e-mail: users-help@activemq.apache.org
For further information, visit: https://activemq.apache.org/contact
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by John <jk...@gmail.com>.
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
On Tue, Mar 10, 2026 at 5:33 PM Timothy Bish <ta...@gmail.com> 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 <ta...@gmail.com>
> 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 <ta...@gmail.com>
> 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: users-unsubscribe@activemq.apache.org
> >>>> For additional commands, e-mail: users-help@activemq.apache.org
> >>>> For further information, visit: https://activemq.apache.org/contact
> >>>>
> >>>>
> >>>>
> >> --
> >> Tim Bish
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> >> For additional commands, e-mail: users-help@activemq.apache.org
> >> For further information, visit: https://activemq.apache.org/contact
> >>
> >>
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> > For additional commands, e-mail: users-help@activemq.apache.org
> > For further information, visit: https://activemq.apache.org/contact
> >
> >
>
> --
> Tim Bish
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> For additional commands, e-mail: users-help@activemq.apache.org
> For further information, visit: https://activemq.apache.org/contact
>
>
>
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by Timothy Bish <ta...@gmail.com>.
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 <ta...@gmail.com> 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 <ta...@gmail.com> 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: users-unsubscribe@activemq.apache.org
>>>> For additional commands, e-mail: users-help@activemq.apache.org
>>>> For further information, visit: https://activemq.apache.org/contact
>>>>
>>>>
>>>>
>> --
>> Tim Bish
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
>> For additional commands, e-mail: users-help@activemq.apache.org
>> For further information, visit: https://activemq.apache.org/contact
>>
>>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> For additional commands, e-mail: users-help@activemq.apache.org
> For further information, visit: https://activemq.apache.org/contact
>
>
--
Tim Bish
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
For additional commands, e-mail: users-help@activemq.apache.org
For further information, visit: https://activemq.apache.org/contact
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by John <jk...@gmail.com>.
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:
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 <ta...@gmail.com> 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 <ta...@gmail.com> 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: users-unsubscribe@activemq.apache.org
> >> For additional commands, e-mail: users-help@activemq.apache.org
> >> For further information, visit: https://activemq.apache.org/contact
> >>
> >>
> >>
>
> --
> Tim Bish
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
> For additional commands, e-mail: users-help@activemq.apache.org
> For further information, visit: https://activemq.apache.org/contact
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
For additional commands, e-mail: users-help@activemq.apache.org
For further information, visit: https://activemq.apache.org/contact
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by Timothy Bish <ta...@gmail.com>.
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 <ta...@gmail.com> 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: users-unsubscribe@activemq.apache.org
>> For additional commands, e-mail: users-help@activemq.apache.org
>> For further information, visit: https://activemq.apache.org/contact
>>
>>
>>
--
Tim Bish
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@activemq.apache.org
For additional commands, e-mail: users-help@activemq.apache.org
For further information, visit: https://activemq.apache.org/contact
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by John <jk...@gmail.com>.
Hi Tim,
Yes, each client has a unique Client ID. And this has been verified.
However, should the Client ID follow a specific pattern?
On Tue, Mar 10, 2026 at 4:17 PM Timothy Bish <ta...@gmail.com> 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: users-unsubscribe@activemq.apache.org
> For additional commands, e-mail: users-help@activemq.apache.org
> For further information, visit: https://activemq.apache.org/contact
>
>
>
Re: Apache.NMS.AMQP 2.4.0 - Connection Uri nms.clientId Issue
Posted by Timothy Bish <ta...@gmail.com>.
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: users-unsubscribe@activemq.apache.org
For additional commands, e-mail: users-help@activemq.apache.org
For further information, visit: https://activemq.apache.org/contact