Is there a way to suppress duplicated messages on a queue defined on ActiveMQ server?
I tried to define manually JMSMessageID, (message.setJMSMessageID(\"uniqueid\")
There is now support for removing duplicate messages baked into ActiveMQ transports. See the configuration values auditDepth
and auditMaximumProducerNumber
in the Connection Configuration Guide.
There is a way to make ActiveMQ to filter duplicates based on a JMS property. it involves writing an Activemq Plugin. A basic broker filter that sends duplicate messages to the deadletter queue would be like this
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.activemq.broker.Broker;
import org.apache.activemq.command.Message;
import org.apache.activemq.command.ActiveMQMessage;
import org.apache.activemq.broker.BrokerFilter;
import org.apache.activemq.broker.ConnectionContext;
import org.apache.activemq.command.ConnectionInfo;
import org.apache.activemq.broker.ProducerBrokerExchange;
public class DuplicateFilterBroker extends BrokerFilter {
String messagePropertyName;
boolean switchValue;
public DuplicateFilterBroker(Broker next, String messagePropertyName) {
super(next);
this.messagePropertyName = messagePropertyName;
}
public boolean hasDuplicate(String propertyValue){
switchValue = propertyValue;
return switchValue;
}
public void send(ProducerBrokerExchange producerExchange, Message msg) throws Exception {
ActiveMQMessage amqmsg = (ActiveMQMessage)msg;
Object msgObj = msg.getMessage();
if (msgObj instanceof javax.jms.Message) {
javax.jms.Message jmsMsg = (javax.jms.Message) msgObj;
if (!hasDuplicate(jmsMsg.getStringProperty(messagePropertyName))) {
super.send(producerExchange, msg);
}
else {
sendToDeadLetterQueue(producerExchange.getConnectionContext(), msg);
}
}
}
}
You should look at Apache Camel, it provides an Idempotent consumer component that would work with any JMS provider, see: http://camel.apache.org/idempotent-consumer.html
Using that in combination with the ActiveMQ component makes using JMS quite simple, see: http://camel.apache.org/activemq.html
I doubt if ActiveMQ supports it natively, but it should be easy to implement an idempotent consumer. A way to do this would be to add a unique identifier to each message at the producer end, now at the consumer end using a store(db, cache etc), a check can be made to see if the message has been received before and continue to process based on that check.
I see a previous stackoverflow question along the same lines - Apache ActiveMQ 5.3 - How to configure a queue to reject duplicate messages? , that may also help.
Seem the way that is suggested in the question, works for ActiveMQ too (2016/12). See the activemq-artemis guide. This requires the producer to set a specific property into the message.
Message jmsMessage = session.createMessage();
String myUniqueID = "This is my unique id"; // Could use a UUID for this
message.setStringProperty(HDR_DUPLICATE_DETECTION_ID.toString(), myUniqueID);
However the class containing the property is different:
org.apache.activemq.artemis.core.message.impl.HDR_DUPLICATE_DETECTION_ID
and the property value is _AMQ_DUPL_ID
.