STOMP messages sent to durable address/queue not surviving reboots - stomp

I'm getting started with ActiveMQ Artemis and would like to send STOMP messages to a queue:
<address name="/queue/default">
<multicast>
<queue name="/queue/default">
<durable>true</durable>
</queue>
</multicast>
</address>
As best to my knowledge as I can tell, I've made a best effort to make it so that messages in this queue will survive a restart, yet for some reason, when I restart my broker, all the messages are gone.
What would I be missing in this situation that could cause this to happen?

Without more details about how you're sending the message it's hard to answer with confidence, but I'm guessing that you're not setting the proper header on the message to indicate that it should be durable/persistent. The STOMP specification doesn't outline the behavior of messages in this regard so it's up to the messaging provider (i.e. ActiveMQ Artemis in this case) to determine the behavior. By default messages will not be durable/persistent so you must set the persistent header on the message to true to make the message durable/persistent.
It's also worth noting that queues are durable by default so you don't really need <durable>true</durable> in the definition as it's redundant.

Related

ActiveMQ 5 redelivery policies ignored with AMQP

I have a Spring Boot application using Qpid JMS to speak AMQP with an ActiveMQ 5.15.14 broker. Even though the redelivery plugin is configured, the redelivery policies of the broker are ignored. However the redelivery policy of the client (Qpid) does come into play.
When the exact same code and client configuration is connected to a ActiveMQ Artemis broker, the redelivery policy of the broker kicks in which is what I'm looking for.
Anything you are aware of that could explain this different behavior between ActiveMQ 5 and ActiveMQ Artemis? Both brokers are using pretty much OOTB configuration aside from the redelivery policies, and schedulerSupport is enabled in my ActiveMQ 5 broker as well. Here's what the redelivey configuration looks like in activemq.xml:
<redeliveryPlugin fallbackToDeadLetter="true" sendToDlqIfMaxRetriesExceeded="true">
<redeliveryPolicyMap>
<redeliveryPolicyMap>
<defaultEntry>
<redeliveryPolicy initialRedeliveryDelay="5000" maximumRedeliveries="9" redeliveryDelay="60000" />
</defaultEntry>
</redeliveryPolicyMap>
</redeliveryPolicyMap>
</redeliveryPlugin>
One more thing to consider : the redelivery policies of the ActiveMQ 5 broker are applied when I use Openwire (JMS) instead of AMQP.
The AMQP protocol head in ActiveMQ 5.x is far more primitive than that of the Artemis broker implementation and is likely not reacting correct to the dispositions that are being sent back from the AMQP client. Also the 5.x broker can react differently based on the transformer setting in the 'transportConnector' on the broker which can be one of JMS, NATIVE or RAW. The JMS transformer will give the most ActiveMQ compatible behaviour but requires a complete transformation internally to an OpenWire message and then back to AMQP when going from AMQP sender to AMQP receiver which can hurt performance significantly. The NATIVE transformation will attempt to preserve some insights into the redelivered state of the message but won't catch every case most likely. With the RAW mode there will be no insight into the message delivery count at all and as such you definitely won't get any redelivery processing on the broker side.
I short, if you are looking for a fully functional AMQP broker then choose Artemis as it has had a lot of work, if you just need something that can get messages flowing then 5.x should work but don't expect the same quality of service.

How to specify topic or queue when sending/subscribing to a JMS object, ActiveMQ Artemis and STOMP

I'm using ActiveMQ Artemis messaging system, and I'm testing my setup with STOMP (stomp.py).
I created an "address" on Artemis called Site.SOF.Order.Fulfillment.Submission.ActiveOmni.Topic, and attached two queues to it:
Site.SOF.Order.Fulfillment.Submission.ActiveOmni.queue (multicast)
Site.SOF.Order.Fulfillment.Submission.ActiveOmni.log.queue (multicast)
Here are the exported bindings:
<bindings>
<address-binding routing-types="ANYCAST" name="DLQ" id="2"/>
<address-binding routing-types="ANYCAST" name="ExpiryQueue" id="6"/>
<address-binding routing-types="MULTICAST" name="activemq.notifications" id="10"/>
<address-binding routing-types="MULTICAST" name="Site.SOF.Order.Fulfillment.Submission.Topic" id="92"/>
<queue-binding address="Site.SOF.Order.Fulfillment.Submission.Topic" filter-string="" name="Site.SOF.Order.Fulfillment.Submission.log.Queue" id="97" routing-type="MULTICAST"/>
<queue-binding address="DLQ" filter-string="" name="DLQ" id="4" routing-type="ANYCAST"/>
<queue-binding address="ExpiryQueue" filter-string="" name="ExpiryQueue" id="8" routing-type="ANYCAST"/>
<queue-binding address="Site.SOF.Order.Fulfillment.Submission.Topic" filter-string="" name="Site.SOF.Order.Fulfillment.Submission.ActiveOmni.Queue" id="94" routing-type="MULTICAST"/>
</bindings>
I created a user with access to Site.*
So how do I access the queues? For example, if I use the stomp.py command line tool like so:
> subscribe Site.SOF.Order.Fulfillment.Submission.ActiveOmni.queue
I get the error:
[username] does not have permission='CREATE_ADDRESS' on address Site.SOF.Order.Fulfillment.Submission.ActiveOmni.queue
So I try adding /queue/ to the front, as I've seen in the tutorials
> subscribe /queue/Site.SOF.Order.Fulfillment.Submission.ActiveOmni.queue
But I get the same error:
[username] does not have permission='CREATE_ADDRESS' on address /queue/Site.SOF.Order.Fulfillment.Submission.ActiveOmni.queue
I can send to the topic/address without trouble. The following results in a "hello" message appearing in both queues.
send Site.SOF.Order.Fulfillment.Submission.ActiveOmni.Topic "hello"
Is this a naming convention I'm missing? Or a way to specify topic vs queue? What am I missing here that's too obvious to be clearly documented?
Let me provide some background information first...
The ActiveMQ Artemis address model includes 3 main elements - addresses, queues, and routing types. These are low-level entities which are used to implement all the different semantics for all the different protocols and configurations the broker supports.
STOMP, by contrast, just supports ambiguous "destinations." The STOMP 1.2 specification says this about destinations:
A STOMP server is modelled as a set of destinations to which messages can be sent. The STOMP protocol treats destinations as opaque string and their syntax is server implementation specific. Additionally STOMP does not define what the delivery semantics of destinations should be. The delivery, or “message exchange”, semantics of destinations can vary from server to server and even from destination to destination. This allows servers to be creative with the semantics that they can support with STOMP.
In the core address model messages are sent to addresses and consumed from queues. Addresses and queues are named independently so the names that the core producer and consumer use can be different.
ActiveMQ Artemis supports both point-to-point and pub/sub semantics for STOMP destinations. You can read more about how to configure these semantics in the latest ActiveMQ Artemis STOMP documentation.
In the STOMP point-to-point use-case a message is sent to a destination and consumed from that same destination. The name that both the STOMP producer and consumer use are the same. In order to support these semantics the broker uses a core address and a core anycast queue with the same name.
In the STOMP pub/sub use-case a client creates a subscription on a destination which it can then use to receive messages sent to that destination. The name that both the STOMP subscriber and producer use are the same. In order to support these semantics the broker uses a core address and a core multicast queue with different names. The name of the core queue is generated by the broker automatically. The subscriber can then receive the messages directly from the underlying core subscription queue.
All this stuff is done behind the scenes for STOMP clients, but it's important to understand how STOMP maps to ActiveMQ Artemis' address model so you can configure things appropriately
In your case you've configured an address with 2 multicast queues and you're trying to consume from those queues. This use-case is a mix between point-to-point and pub/sub because you have statically defined queues (i.e. not queues auto-created by the broker in response to a subscriber) but the queues are multicast. These queues are like statically configured durable subscriptions. To access the queues directly you need to use their fully-qualified queue name (i.e. FQQN) from your client. The FQQN follows the pattern of <address>::<queue> so in your case you'd use either
Site.SOF.Order.Fulfillment.Submission.ActiveOmni.Topic::Site.SOF.Order.Fulfillment.Submission.ActiveOmni.queue
or
Site.SOF.Order.Fulfillment.Submission.ActiveOmni.Topic::Site.SOF.Order.Fulfillment.Submission.ActiveOmni.log.queue

Are there any benefits in using the "failover:" protocol with the "vm:" transport in ActiveMQ?

According to this answer, there are benefits from using the "failover" protocol with a "tcp" transport, even with a single address.
In addition to this, the ActiveMQ documentation, the following applies (emphasis mine):
If a JMS broker goes down, ActiveMQ can automatically reconnect to an available JMS broker using the failover: protocol. Not only does this automatically reconnect, it will also resume any temporary destinations, sessions, producers and most importantly consumers.
Does this also apply when using the "vm" transport?
We are seeing frequent issues with queue consumers stopping to pick up messages, while the queue fills up, and we have not found a fix for this yet. This is with ActiveMQ v5.6.0 - we're upgrading to v5.14.5 at the moment, but want to explore additional options, too.
Our current Spring configuration for the ActiveMQConnectionFactory looks like this:
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"
depends-on="amqEmbeddedBroker">
<property name="brokerURL" value="vm://localhost" />
<property name="watchTopicAdvisories" value="false" />
</bean>
Would changing the URL from vm://localhost to failover:(vm://localhost) provide any benefit in this case, i.e. safe-guarding against connections being closed for whatever reason? When changing the URL to include the failover: part, I can see that an instance of FailoverTransport is created, but does it provide any benefit in the case of the vm transport?
Failover will try to get a reconnection if the connection fails. So if you're doing an operation that would normally crash of connection failure, you won't see an exception but it will silently try to reconnect. So if your in memory broker goes dead, the client will be silent and perhaps issue some log that it tries to reconnect.
VM connections do not fail because of network issues, so you may want to investigate further. But upgrading seems like the first step.

Solace - Message delivery count

We are using Solace as messaging broker. How can I get the number of times a message is delivered from broker? In Jboss, there is a property called JMSXDeliveryCount. Is there anything similar in Solace?
The Solace JMS API is compliant with JMS1.1.
Unfortunately, JMSXDeliveryCount is an optional property in the JMS1.1 specification that is not implemented by the Solace JMS API.
For now, you can keep track of redelivered messages with JMSRedelivered, which does not provide the count.
If you are worried about application handling of "poisonous" messages - messages which cannot be consumed for some reason and need to be redelivered, you can make use of the "Max Redelivery" feature on the Solace endpoints. Messages will be moved to the Dead Message Queue or even configured to be discarded, when the message has been redelivered above the "Max Redelivery" count.
Support for JMSXDeliveryCount is in Solace's feature candidate list, and is likely to be implemented in a future release.

JMS: publisher publishes to queue, subscriber would like to read like it was a topic

I have a JMS publisher, which I cannot change (external system). This publisher publishes messages into some predefined JMS queue. I would like to design a multi-node subscriber system in which all subscribing nodes will receive a copy of each message (in my design, a subscriber node is able to realize if the message is targeted at this node by checking some property inside the message, so only one subscriber node will eventually process the message, while other subscriber nodes will discard their copies).
Changing the publisher system to use Topics could work flawlessly, but I cannot change the publisher.
Currently, I see two options to solve this:
One option which can probably work is to use QueueBrowser, implement periodic polling which will read all messages and if the message is "mine", remove the message from queue and process. This is a huge overhead for such a simple problem.
Another option is to write a dispatcher which subscribes to the queue and dispatches each message to multiple "internal" subscribers (e.g. as explained here: JMS - Going from one to multiple consumers). But this creates bottleneck in the dispatcher killing the whole scalability idea.
A third option is to have multiple "intermediate" queue subscribers, each subscriber, when it receives a message, re-publishes it to a Topic for which the target subscribers will subscribe. This can work, but it's an extra hop in the flow, so not sure if the benefit (scalability) will be worth the loss (latency and complexity).
I wonder if there are any other ideas on how to solve this.
Can I have a subscriber listening to all topics ?
Can I configure JMS (WebLogic in my case) to auto-forward messages from queue to some topic?
Other options?
Thanks.
With the Oracle Service Bus you can route Queues to Topics like you mentioned in #2 above. It's an optional piece of middleware that can be installed with Weblogic. It has all sorts of routing options for JMS and web services.
Here is a quick look:
http://www.orafmwschool.com/oracle-service-bus-routing-and-transformation/
http://www.slideshare.net/gschmutz/where-andwhentousetheoracleservicebusv2
We are using it for very much the same purpose that you're looking for.
Take a look at JMS routing using Apache CAMEL
<camelContext id="camel" xmlns="http://activemq.apache.org/camel/schema/spring">
<!-- simple bridge from a topic to queue -->
<route>
<from uri="activemq:topic:topic.HelloWorld.incoming"> <to uri="activemq:queue:queue.HelloWorld">
</route>
</camelContext>

Resources