I'm trying to send 2 different messages to a queue where there is no SEND
permission. In the case of setting producer.setDeliveryMode(DeliveryMode.PERSISTENT)
everything is fine (the error is displayed in the console), but if I set the value producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT)
then there will be no error and the message will not be sent to the queue. I would like the error to be reproduced in two cases or is this a feature of the broker?
My broker.xml
:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<configuration xmlns="urn:activemq"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:activemq /schema/artemis-configuration.xsd">
<core xmlns="urn:activemq:core">
<name>localhost</name>
<bindings-directory>./data/messaging/bindings</bindings-directory>
<journal-directory>./data/messaging/journal</journal-directory>
<large-messages-directory>./data/messaging/largemessages</large-messages-directory>
<paging-directory>./data/messaging/paging</paging-directory>
<!-- true to expose ActiveMQ Artemis resources through JMX -->
<jmx-management-enabled>true</jmx-management-enabled>
<!-- Acceptors -->
<acceptors>
<acceptor name="netty">tcp://localhost:61616</acceptor>
</acceptors>
<!-- Other config -->
<security-settings>
<!--security for example queue-->
<security-setting match="exampleQueue">
<permission roles="amq" type="createDurableQueue"/>
<permission roles="amq" type="deleteDurableQueue"/>
<permission roles="amq" type="createNonDurableQueue"/>
<permission roles="amq" type="deleteNonDurableQueue"/>
<permission roles="amq" type="consume"/>
<permission roles="no" type="send"/>
<permission roles="amq" type="browse"/>
</security-setting>
<security-setting match="TestQueue">
<permission roles="amq" type="createDurableQueue"/>
<permission roles="amq" type="deleteDurableQueue"/>
<permission roles="amq" type="createNonDurableQueue"/>
<permission roles="amq" type="deleteNonDurableQueue"/>
<permission roles="amq" type="consume"/>
<permission roles="no" type="send"/>
<permission roles="amq" type="browse"/>
</security-setting>
<security-setting match="TestQueueSecond">
<permission roles="amq" type="createDurableQueue"/>
<permission roles="amq" type="deleteDurableQueue"/>
<permission roles="amq" type="createNonDurableQueue"/>
<permission roles="amq" type="deleteNonDurableQueue"/>
<permission roles="no" type="consume"/>
<permission roles="no" type="send"/>
</security-setting>
</security-settings>
<addresses>
<address name="exampleQueue">
<anycast>
<queue name="exampleQueue"/>
</anycast>
</address>
<address name="TestQueue">
<anycast>
<queue name="TestQueue"/>
</anycast>
</address>
<address name="TestQueueSecond">
<anycast>
<queue name="TestQueueSecond"/>
</anycast>
</address>
</addresses>
</core>
</configuration>
My class java:
@RestController
public class Producer implements Serializable {
String url = "tcp://localhost:61616";
@GetMapping("/send")
public String sendMessage() throws JMSException {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
connectionFactory.setUser("test");
connectionFactory.setPassword("qwe123");
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("exampleQueue");
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
Message message = session.createTextMessage("BodyTextMessage");
message.setStringProperty("TEST", "TEST");
producer.send(message);
String body = message.getBody(String.class);
connection.close();
return body;
}
This is exactly the example when I send a message to the queue, but there is no error that the message cannot be sent because there is no permission to send.
When sending a non-persistent message the core JMS client from ActiveMQ Artemis uses "fire-and-forget" semantics which means it doesn't wait to determine if the send was successful or not; it simply returns control to the sending application. This is a performance optimization based on the fact that non-persistent messages are by nature volatile. In other words, since non-persistent messages do not survive a broker restart that means their loss is acceptable.
You can change these semantics by setting blockOnNonDurableSend=true
on your connection URL, e.g.:
String url = "tcp://localhost:61616?blockOnNonDurableSend=true";
This, of course, will make sending non-persistent messages much slower. See more in the documentation.