I've started looking at JBMESSAGING-38: QueueBrowser.
I'm knocking together an initial swipe at this, and wanted to check my design approach with you.
I'm implementing a new delegate: BrowserDelegate which supports the distilled down functionality for the QueueBrowser. The client side proxy is created (as per normal pattern) in the server delegate, in this case ServerSessionDelegate.
I've created a JBossQueueBrowser class that implements QueueBrowser, this is what the user of JMS handles. This doesn't hold any state and just calls the delegate to get it's job done.
As to how to get the messages from the server to the client so they can be browsed, I can think of two main approaches here:
1. Get all the messages in the queue in one go from the server and serialise them to the client (if not colocated), then create an enumeration over them for the jms user to use.
2. Chunk the messages either one-by-one from the server or in configurable "batch sizes" (is that the right term?), e.g. get the messages 50 at a time from the server (this can be configurable). This is transparent to the JMS User who is just smoothly enumerating through an enumeration.
Option 1, seems to be the approach that SpyderMQ uses. I could be wrong, but I'm guessing there might be problems here both with the initial time expense in starting the enumeration, and with client side memory usage if there are a lot of undelivered messages.
So, so far I'm going with Option 2 - I would greatly appreciate your input here as to whether this is a sound decision.
The "batching" I'm doing in a new client side interceptor "BrowserInterceptor". I haven't worked out yet how this would be configurable.
My second main issue, is how to see the messages in the queue in the first place, using the core classes.
My initial thought here is to get the message ids of the unacked messages using getUnacknowledged() on the channel and then looking them up in the message store.
Currently the getUnacknowledged() implementation for the queue locks the queue and creates the unacked ids in a new Set before returning it. I'm not sure if this is necessary for browsing since according to the JMS spec we don't have to guarantee a static snapshot of the queue. My thoughts are that not locking or creating a new Set could perhaps improve concurrency and memory usage.
Again, I'd appreciate your thoughts on this.
The current Channel interface is not rich enough to allow browsing. getUnacknowledged()/hasMessages() currently refer to the union between the set of messages that have not been acknowledged at all (for example the messages being held by a queue with no receivers) and the set of messages that have been delivered, but then NACKed. The current JBossMQ implementation of BasicQueue.browse() returns only to the first set. Probably the best thing to do is to add a browse() method to the Channel. Do you want to take a look at that?
Ok, will do
Currently, all the Channel implementations in core seem to first attempt synchronous delivery, and only if that is not possible is the message stored as NACKed.
According to that logic, the only messages that will be stored in the channel, and therefore browsable are NACKed messages.
If we want to be able to distinguish between the two sets of messages that you refer to, then I believe we would have to change this core logic - is this something we really want to do?
The conclusion of this discussion thead http://www.jboss.org/index.html?module=bb&op=viewtopic&t=63511, is that all messages will be initally NACKed by the facade, and then asynchronously ACKed if the case, so all of them will be stored by the Channel.
The difference between a message that was NACKed and a message that has never been delivered could be that the acknowledgment store remembers (M - null) for a never delivered message and (M - ReceiverID) for a NACKed message.
I don't think there is need to change the Channel delivery strategy to distinguish between these to, but to add necessary behavior to the Channel/Acknowledgment store.