1818
1919import org .apache .activemq .ActiveMQConnectionFactory ;
2020import org .apache .activemq .broker .BrokerService ;
21+ import org .apache .activemq .command .ActiveMQQueue ;
22+ import org .apache .activemq .network .DiscoveryNetworkConnector ;
23+ import org .apache .activemq .util .Wait ;
2124import org .junit .Test ;
2225import org .junit .runner .RunWith ;
2326import org .slf4j .Logger ;
2730
2831import jakarta .annotation .Resource ;
2932import jakarta .jms .*;
33+ import java .net .URI ;
3034import java .util .concurrent .CountDownLatch ;
35+ import java .util .concurrent .TimeUnit ;
3136
3237import static org .junit .Assert .assertEquals ;
38+ import static org .junit .Assert .assertTrue ;
3339
3440@ RunWith (SpringJUnit4ClassRunner .class )
3541@ ContextConfiguration ({ "virtual-topic-network-test.xml" })
@@ -53,45 +59,64 @@ public class MessageDestinationVirtualTopicTest {
5359
5460 private Session session1 ;
5561
56- public void init () throws JMSException {
62+ public void init () throws Exception {
63+ // Get actual assigned ephemeral ports
64+ final String broker1URL = broker1 .getTransportConnectors ().get (0 ).getConnectUri ().toString ();
65+ final String broker2URL = broker2 .getTransportConnectors ().get (0 ).getConnectUri ().toString ();
66+ LOG .info ("Broker1 URL: {}" , broker1URL );
67+ LOG .info ("Broker2 URL: {}" , broker2URL );
68+
69+ // Add network connector from broker2 to broker1 programmatically using actual port
70+ final DiscoveryNetworkConnector nc = new DiscoveryNetworkConnector (
71+ new URI ("static://(" + broker1URL + ")" ));
72+ nc .setName ("linkToBrokerB1" );
73+ nc .setNetworkTTL (1 );
74+ nc .setDuplex (true );
75+ broker2 .addNetworkConnector (nc );
76+ nc .start ();
77+
78+ // Wait for bridge to be established
79+ assertTrue ("Network bridge should be established" ,
80+ Wait .waitFor (() -> nc .activeBridges ().size () == 1 , 10_000 , 500 ));
81+
5782 // Create connection on Broker B2
58- ConnectionFactory broker2ConnectionFactory = new ActiveMQConnectionFactory ("tcp://localhost:62616" );
59- Connection connection2 = broker2ConnectionFactory .createConnection ();
83+ final ConnectionFactory broker2ConnectionFactory = new ActiveMQConnectionFactory (broker2URL );
84+ final Connection connection2 = broker2ConnectionFactory .createConnection ();
6085 connection2 .start ();
61- Session session2 = connection2 .createSession (false , Session .AUTO_ACKNOWLEDGE );
62- Queue consumerDQueue = session2 .createQueue ("Consumer.D.VirtualTopic.T1" );
86+ final Session session2 = connection2 .createSession (false , Session .AUTO_ACKNOWLEDGE );
87+ final Queue consumerDQueue = session2 .createQueue ("Consumer.D.VirtualTopic.T1" );
6388
6489 // Bind listener on queue for consumer D
65- MessageConsumer consumer = session2 .createConsumer (consumerDQueue );
90+ final MessageConsumer consumer = session2 .createConsumer (consumerDQueue );
6691 listener2 = new SimpleMessageListener ();
6792 consumer .setMessageListener (listener2 );
6893
6994 // Create connection on Broker B1
70- ConnectionFactory broker1ConnectionFactory = new ActiveMQConnectionFactory ("tcp://localhost:61616" );
71- Connection connection1 = broker1ConnectionFactory .createConnection ();
95+ final ConnectionFactory broker1ConnectionFactory = new ActiveMQConnectionFactory (broker1URL );
96+ final Connection connection1 = broker1ConnectionFactory .createConnection ();
7297 connection1 .start ();
7398 session1 = connection1 .createSession (false , Session .AUTO_ACKNOWLEDGE );
74- Queue consumerCQueue = session1 .createQueue ("Consumer.C.VirtualTopic.T1" );
99+ final Queue consumerCQueue = session1 .createQueue ("Consumer.C.VirtualTopic.T1" );
75100
76- // Bind listener on queue for consumer D
77- MessageConsumer consumer1 = session1 .createConsumer (consumerCQueue );
101+ // Bind listener on queue for consumer C
102+ final MessageConsumer consumer1 = session1 .createConsumer (consumerCQueue );
78103 listener1 = new SimpleMessageListener ();
79104 consumer1 .setMessageListener (listener1 );
80105
81- // Create listener on Broker B1 for VT T2 witout setOriginalDest
82- Queue consumer3Queue = session1 .createQueue ("Consumer.A.VirtualTopic.T2" );
106+ // Create listener on Broker B1 for VT T2 without setOriginalDest
107+ final Queue consumer3Queue = session1 .createQueue ("Consumer.A.VirtualTopic.T2" );
83108
84- // Bind listener on queue for consumer D
85- MessageConsumer consumerD = session1 .createConsumer (consumer3Queue );
109+ // Bind listener on queue for consumer A
110+ final MessageConsumer consumerD = session1 .createConsumer (consumer3Queue );
86111 listener3 = new SimpleMessageListener ();
87112 consumerD .setMessageListener (listener3 );
88113
89114 // Create producer for topic, on B1
90- Topic virtualTopicT1 = session1 .createTopic ("VirtualTopic.T1,VirtualTopic.T2" );
115+ final Topic virtualTopicT1 = session1 .createTopic ("VirtualTopic.T1,VirtualTopic.T2" );
91116 producer = session1 .createProducer (virtualTopicT1 );
92117 }
93118
94- @ Test
119+ @ Test ( timeout = 30_000 )
95120 public void testDestinationNames () throws Exception {
96121
97122 LOG .info ("Started waiting for broker 1 and 2" );
@@ -102,32 +127,46 @@ public void testDestinationNames() throws Exception {
102127 init ();
103128
104129 // Create a monitor
105- CountDownLatch monitor = new CountDownLatch (3 );
130+ final CountDownLatch monitor = new CountDownLatch (3 );
106131 listener1 .setCountDown (monitor );
107132 listener2 .setCountDown (monitor );
108133 listener3 .setCountDown (monitor );
109134
135+ // Wait for the consumer on broker2 to be visible on broker1 via the network bridge.
136+ // The virtual topic Consumer.D.VirtualTopic.T1 on broker2 must be forwarded to broker1
137+ // before sending, otherwise the message won't reach listener2.
138+ assertTrue ("Consumer.D queue should exist on broker1 via network bridge" ,
139+ Wait .waitFor (() -> {
140+ try {
141+ final org .apache .activemq .broker .region .Destination dest =
142+ broker1 .getDestination (new ActiveMQQueue ("Consumer.D.VirtualTopic.T1" ));
143+ return dest != null && dest .getConsumers ().size () >= 1 ;
144+ } catch (final Exception e ) {
145+ return false ;
146+ }
147+ }, 10_000 , 200 ));
148+
110149 LOG .info ("Sending message" );
111150 // Send a message on the topic
112- TextMessage message = session1 .createTextMessage ("Hello World !" );
151+ final TextMessage message = session1 .createTextMessage ("Hello World !" );
113152 producer .send (message );
114153 LOG .info ("Waiting for message reception" );
115154 // Wait the two messages in the related queues
116- monitor .await ();
155+ assertTrue ( "All 3 listeners should receive messages" , monitor .await (15 , TimeUnit . SECONDS ) );
117156
118157 // Get the message destinations
119- String lastJMSDestination2 = listener2 .getLastJMSDestination ();
120- System . err . println ( lastJMSDestination2 );
121- String lastJMSDestination1 = listener1 .getLastJMSDestination ();
122- System . err . println ( lastJMSDestination1 );
158+ final String lastJMSDestination2 = listener2 .getLastJMSDestination ();
159+ LOG . info ( "Listener2 destination: {}" , lastJMSDestination2 );
160+ final String lastJMSDestination1 = listener1 .getLastJMSDestination ();
161+ LOG . info ( "Listener1 destination: {}" , lastJMSDestination1 );
123162
124- String lastJMSDestination3 = listener3 .getLastJMSDestination ();
125- System . err . println ( lastJMSDestination3 );
163+ final String lastJMSDestination3 = listener3 .getLastJMSDestination ();
164+ LOG . info ( "Listener3 destination: {}" , lastJMSDestination3 );
126165
127166 // The destination names
128167 assertEquals ("queue://Consumer.D.VirtualTopic.T1" , lastJMSDestination2 );
129168 assertEquals ("queue://Consumer.C.VirtualTopic.T1" , lastJMSDestination1 );
130169 assertEquals ("topic://VirtualTopic.T2" , lastJMSDestination3 );
131170
132171 }
133- }
172+ }
0 commit comments