I have three machines located in different networks:
- as-master
- as-node-1
- as-node-2
In as-master I have WildFly as domain host-master and the two nodes have WildFly as domain host-slave each starting an instance in the full-ha server group. From the as-master web console I can see the two nodes in the full-ha profile runtime and if I deploy a WAR it gets correctly started on both nodes.
Now, what I'm trying to achieve is messaging between the two instances of the WAR, i.e. sending a message from a producer instance in as-node-1, consumers in all the nodes should receive the message.
This is what I tried: added a topic to WildFly domain.xml
:
<jms-topic name="MyTopic" entries="java:/jms/my-topic"/>
Create a JAX-RS endpoint to trigger a producer bound to the topic:
@Path("jms")
@RequestScoped
public class MessageEndpoint {
@Inject
JMSContext context;
@Resource(mappedName = "java:/jms/my-topic")
Topic myTopic;
@GET
public void sendMessage() {
this.context.createProducer().send(this.myTopic, "Hello!");
}
}
Create a MDB listening to the topic:
@MessageDriven(activationConfig = {
@ActivationConfigProperty(
propertyName = "destination",
propertyValue = "java:/jms/my-topic"
),
@ActivationConfigProperty(
propertyName = "destinationType",
propertyValue = "javax.jms.Topic")
)
)
public class MyMessageListener implements MessageListener {
private final static Logger LOGGER = /* ... */
public void onMessage(Message message) {
try {
String body = message.getBody(String.class)
LOGGER.info("Received message: " + body);
} catch (JMSException e) {
throw new RuntimeException(e);
}
}
}
But when I curl as-node-1/jms
I see the log only in as-node-1, and when I curl as-node-2/jms
I see the log only in as-node-2.
Shouldn't the message be delivered on all the nodes where the WAR is deployed? What am I missing?
As I've come with the exactly same question - put the answer here.
Yes, messages should be delivered to all nodes if a destination is a Topic.
With the default configuration ActiveMQ Artemis uses broadcast to discover and connect to other ActiveMQ instances on other nodes (within the same discovery-group):
Still need to ensure that a JNDI name for a jms-topic starts with the "jms" to match the
address="jms"
in the line above (what is OK in your case: "java:/jms/my-topic
")The only thing missed in your example to get it working on all nodes is :
<cluster password="yourPassword" user="activemqUser"/>
(for sure
activemqUser
user must be added earlier, e.g. with the addUser.sh script).This let ActiveMQ instances to communicate each other. So called Core Bridge connection is created between nodes. As stated in ActiveMQ manual :
If everything is OK then the bridge may be found in server.log:
AMQ221027: Bridge ClusterConnectionBridge@63549ead [name=sf.my-cluster ...] is connected.
Btw, if a destination is a Queue then ActiveMQ will not send a message to other nodes unless a message is not consumed locally.
P.s. as answered here this refers to a classic approach to distribute an event to all nodes in a cluster.