Skip to content

Commit c373473

Browse files
Old bindingkey is removed if binding key is changed in configuration (#468)
* Added property in configuration to handle the bindings in RabbitMQ when new bindings are added and old bindings are removed. * Added functionality to handle the above property * Added documentation for the above change.
1 parent ac8eb9c commit c373473

File tree

8 files changed

+207
-5
lines changed

8 files changed

+207
-5
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<modelVersion>4.0.0</modelVersion>
77
<groupId>com.github.ericsson</groupId>
88
<artifactId>eiffel-intelligence</artifactId>
9-
<version>2.2.2</version>
9+
<version>2.2.3</version>
1010
<packaging>war</packaging>
1111

1212
<parent>

src/functionaltests/java/com/ericsson/ei/rabbitmq/configuration/RabbitMQConfigurationTestSteps.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
package com.ericsson.ei.rabbitmq.configuration;
22

33
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNotNull;
45

56
import java.io.File;
67
import java.util.ArrayList;
78
import java.util.List;
89

10+
import org.json.JSONObject;
911
import org.junit.Ignore;
1012
import org.slf4j.Logger;
1113
import org.slf4j.LoggerFactory;
14+
import org.springframework.amqp.core.Binding;
15+
import org.springframework.amqp.core.Binding.DestinationType;
1216
import org.springframework.amqp.core.BindingBuilder;
1317
import org.springframework.amqp.core.Queue;
1418
import org.springframework.amqp.core.TopicExchange;
@@ -23,9 +27,11 @@
2327
import org.springframework.util.SocketUtils;
2428

2529
import com.ericsson.ei.handlers.EventHandler;
30+
import com.ericsson.ei.handlers.MongoDBHandler;
2631
import com.ericsson.ei.handlers.RmqHandler;
2732
import com.ericsson.ei.utils.AMQPBrokerManager;
2833
import com.ericsson.ei.utils.FunctionalTestBase;
34+
import com.mongodb.BasicDBObject;
2935

3036
import cucumber.api.java.en.Given;
3137
import cucumber.api.java.en.Then;

src/functionaltests/java/com/ericsson/ei/rabbitmq/connection/RabbitMQTestConnectionSteps.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
package com.ericsson.ei.rabbitmq.connection;
22

33
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNotNull;
45

56
import java.io.File;
67
import java.util.ArrayList;
78
import java.util.List;
89
import java.util.concurrent.TimeUnit;
910

11+
import org.json.JSONObject;
1012
import org.junit.Ignore;
1113
import org.slf4j.Logger;
1214
import org.slf4j.LoggerFactory;
15+
import org.springframework.amqp.core.Binding;
1316
import org.springframework.amqp.core.BindingBuilder;
1417
import org.springframework.amqp.core.Queue;
1518
import org.springframework.amqp.core.TopicExchange;
19+
import org.springframework.amqp.core.Binding.DestinationType;
1620
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
1721
import org.springframework.amqp.rabbit.core.RabbitAdmin;
1822
import org.springframework.amqp.rabbit.core.RabbitTemplate;
@@ -24,9 +28,11 @@
2428
import org.springframework.util.SocketUtils;
2529

2630
import com.ericsson.ei.handlers.EventHandler;
31+
import com.ericsson.ei.handlers.MongoDBHandler;
2732
import com.ericsson.ei.handlers.RmqHandler;
2833
import com.ericsson.ei.utils.AMQPBrokerManager;
2934
import com.ericsson.ei.utils.FunctionalTestBase;
35+
import com.mongodb.BasicDBObject;
3036

3137
import cucumber.api.java.en.Given;
3238
import cucumber.api.java.en.Then;
@@ -35,6 +41,7 @@
3541
@Ignore
3642
@TestPropertySource(properties = {
3743
"spring.data.mongodb.database: RabbitMQTestConnectionSteps",
44+
"bindingkeys.collection.name: RabbitMQConfigurationTestSteps-bindingKeys",
3845
"missedNotificationDataBaseName: RabbitMQTestConnectionSteps-missedNotifications",
3946
"rabbitmq.exchange.name: RabbitMQTestConnectionSteps-exchange",
4047
"rabbitmq.consumerName: RabbitMQTestConnectionStepsConsumer" })
@@ -48,6 +55,9 @@ public class RabbitMQTestConnectionSteps extends FunctionalTestBase {
4855

4956
private static final String DEFAULT_ROUTING_KEY = "#";
5057

58+
private static final String BINDING_KEY_1 = "binding-key-1";
59+
private static final String BINDING_KEY_2 = "binding-key-2";
60+
5161
private AMQPBrokerManager amqpBroker;
5262

5363
@Autowired
@@ -57,6 +67,15 @@ public class RabbitMQTestConnectionSteps extends FunctionalTestBase {
5767
@Autowired
5868
EventHandler eventHandler;
5969

70+
@Value("${spring.data.mongodb.database}")
71+
private String dataBaseName;
72+
73+
@Value("${bindingkeys.collection.name}")
74+
private String collectionName;
75+
76+
@Autowired
77+
private MongoDBHandler mongoDBHandler;
78+
6079
@Given("^We are connected to message bus$")
6180
public void connect_to_message_bus() throws Exception {
6281
int port = SocketUtils.findAvailableTcpPort();
@@ -108,6 +127,19 @@ public void can_send_events_which_are_put_in_the_waitlist() throws Exception {
108127
assertEquals(1, waitListSize);
109128
}
110129

130+
@When("^add the binding documents to mongoDB$")
131+
public void add_the_binding_documents_to_mongoDB() {
132+
BasicDBObject dbBinding = insertBinding();
133+
assertNotNull(dbBinding);
134+
}
135+
136+
@Then("^compare the binding keys and remove the old binding keys from rabbitMQ and mongoDB$")
137+
public void compare_the_binding_keys_and_remove_the_old_binding_keys_from_rabbitMQ_and_mongoDB() {
138+
LOGGER.debug("comparing the binding keys to remove the old binding key");
139+
ArrayList<String> removedBinding = compareAndRemoveBindings();
140+
assertEquals(1, removedBinding.size());
141+
}
142+
111143
/**
112144
* This method collects all the event names of events we will send to the
113145
* message bus.
@@ -138,4 +170,33 @@ private RabbitAdmin createExchange(final RmqHandler rmqHandler) {
138170
return admin;
139171
}
140172

173+
private BasicDBObject insertBinding() {
174+
BasicDBObject docInput = new BasicDBObject();
175+
docInput.put("destination", "ei-domain.eiffel-intelligence.messageConsumer.durable");
176+
docInput.put("destinationType", "QUEUE");
177+
docInput.put("exchange", "ei-binding-keys");
178+
docInput.put("bindingKeys", BINDING_KEY_1);
179+
docInput.put("arg", null);
180+
mongoDBHandler.insertDocument(dataBaseName, collectionName, docInput.toString());
181+
return docInput;
182+
}
183+
184+
private ArrayList<String> compareAndRemoveBindings() {
185+
ArrayList<Binding> listBinding = new ArrayList<Binding>();
186+
listBinding.add(new Binding("ei-domain.eiffel-intelligence.messageConsumer.durable", DestinationType.QUEUE,
187+
"ei-binding-keys", BINDING_KEY_2, null));
188+
List<String> allObjects = mongoDBHandler.getAllDocuments(dataBaseName, collectionName);
189+
ArrayList<String> removedBinding = new ArrayList<String>();
190+
191+
JSONObject dbBinding = new JSONObject(allObjects.get(0));
192+
String mongoDbBinding = dbBinding.getString("bindingKeys");
193+
if (!(listBinding.contains(mongoDbBinding))) {
194+
removedBinding.add(mongoDbBinding);
195+
listBinding.remove(0);
196+
String condition = "{\"bindingKeys\": /.*" + mongoDbBinding + "/}";
197+
mongoDBHandler.dropDocument(dataBaseName, collectionName, condition);
198+
}
199+
return removedBinding;
200+
}
201+
141202
}

src/functionaltests/resources/features/rabbitMQTestConnection.feature

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,9 @@ Feature: Test Rabbit MQ Connection
77
When Message bus goes down
88
And Message bus is restarted
99
Then I can send events which are put in the waitlist
10+
11+
@RabbitMQConfigurationDeleteBindingKeysScenario
12+
Scenario: Test that old binding keys are deleted from rabbitMQ and mongoDB
13+
Given We are connected to message bus
14+
When add the binding documents to mongoDB
15+
Then compare the binding keys and remove the old binding keys from rabbitMQ and mongoDB

src/main/java/com/ericsson/ei/handlers/RmqHandler.java

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,34 @@
1717
package com.ericsson.ei.handlers;
1818

1919
import java.util.ArrayList;
20+
import java.util.Arrays;
2021
import java.util.List;
21-
22+
import org.json.JSONObject;
2223
import org.slf4j.Logger;
2324
import org.slf4j.LoggerFactory;
2425
import org.springframework.amqp.core.AcknowledgeMode;
26+
import org.springframework.amqp.core.AmqpAdmin;
2527
import org.springframework.amqp.core.Binding;
28+
import org.springframework.amqp.core.Binding.DestinationType;
2629
import org.springframework.amqp.core.BindingBuilder;
2730
import org.springframework.amqp.core.Queue;
2831
import org.springframework.amqp.core.TopicExchange;
2932
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
3033
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
34+
import org.springframework.amqp.rabbit.core.RabbitAdmin;
3135
import org.springframework.amqp.rabbit.core.RabbitTemplate;
3236
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
3337
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
3438
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
3539
import org.springframework.amqp.rabbit.support.CorrelationData;
40+
import org.springframework.beans.factory.annotation.Autowired;
3641
import org.springframework.beans.factory.annotation.Value;
3742
import org.springframework.context.annotation.Bean;
3843
import org.springframework.stereotype.Component;
3944

4045
import com.ericsson.ei.listener.EIMessageListenerAdapter;
4146
import com.fasterxml.jackson.annotation.JsonIgnore;
47+
import com.mongodb.BasicDBObject;
4248

4349
import lombok.Getter;
4450
import lombok.Setter;
@@ -108,9 +114,23 @@ public class RmqHandler {
108114
@Setter
109115
@Value("${rabbitmq.consumerName}")
110116
private String consumerName;
117+
118+
@Getter
119+
@Setter
120+
@Value("${spring.data.mongodb.database}")
121+
private String dataBaseName;
122+
123+
@Getter
124+
@Setter
125+
@Value("${bindingkeys.collection.name}")
126+
private String collectionName;
111127

112128
@Value("${threads.maxPoolSize}")
113129
private int maxThreads;
130+
131+
@Setter
132+
@Autowired
133+
private MongoDBHandler mongoDBHandler;
114134

115135
@Setter
116136
@JsonIgnore
@@ -122,6 +142,10 @@ public class RmqHandler {
122142
@JsonIgnore
123143
private SimpleMessageListenerContainer container;
124144

145+
@Getter
146+
@JsonIgnore
147+
private AmqpAdmin amqpAdmin;
148+
125149
@Bean
126150
public ConnectionFactory connectionFactory() {
127151
cachingConnectionFactory = new CachingConnectionFactory(host, port);
@@ -171,15 +195,75 @@ Binding binding() {
171195
}
172196

173197
@Bean
174-
public List<Binding> bindings() {
175-
final String[] bingingKeysArray = splitBindingKeys(bindingKeys);
198+
public List<Binding> bindings(){
199+
final String[] bindingKeysArray = splitBindingKeys(bindingKeys);
176200
final List<Binding> bindingList = new ArrayList<>();
177-
for (final String bindingKey : bingingKeysArray) {
201+
for (final String bindingKey : bindingKeysArray) {
178202
bindingList.add(BindingBuilder.bind(externalQueue()).to(exchange()).with(bindingKey));
179203
}
204+
deleteBindings(bindingKeysArray,bindingList);
180205
return bindingList;
181206
}
182207

208+
/**
209+
* This method is used to delete the bindings in rabbitMQ.
210+
* By comparing the binding keys used in the properties and binding keys stored in mongoDB.
211+
* newBindingKeysArray is the only binding keys array.
212+
* AMQPBindingObjectList is entire list of bindings.
213+
* Binding key which is not present in the current AMQPBindingObjectList gets deleted and removed from mongoDB.
214+
* @return
215+
*/
216+
217+
private void deleteBindings(String[] newBindingKeysArray, List<Binding> AMQPBindingObjectList) {
218+
// Creating BindingKeys Collection in mongoDB
219+
ArrayList<String> allDocuments = mongoDBHandler.getAllDocuments(dataBaseName, collectionName);
220+
ArrayList<String> existingBindingsData = new ArrayList<String>();
221+
if (!allDocuments.isEmpty()) {
222+
for (String bindings : allDocuments) {
223+
JSONObject bindingObj = new JSONObject(bindings);
224+
final String mongoDbBindingKey = bindingObj.getString("bindingKeys");
225+
String condition = "{\"bindingKeys\": /.*" + mongoDbBindingKey + "/}";
226+
if (!Arrays.asList(newBindingKeysArray).contains(mongoDbBindingKey)) {
227+
String destinationDB = bindingObj.getString("destination");
228+
String exchangeDB = bindingObj.getString("exchange");
229+
// Binding the old binding key and removing from queue
230+
Binding b = new Binding(destinationDB, DestinationType.QUEUE, exchangeDB, mongoDbBindingKey, null);
231+
amqpAdmin = new RabbitAdmin(connectionFactory());
232+
amqpAdmin.removeBinding(b);
233+
// Removing binding document from mongoDB
234+
mongoDBHandler.dropDocument(dataBaseName, collectionName, condition);
235+
} else {
236+
// storing the existing key into an array.
237+
existingBindingsData.add(mongoDbBindingKey);
238+
}
239+
}
240+
}
241+
// To store the new binding key into the mongoDB.
242+
storeNewBindingKeys(existingBindingsData, AMQPBindingObjectList);
243+
}
244+
245+
/**
246+
* This method is used to store the bindings of new binding key into mongoDB.
247+
* @return
248+
*/
249+
250+
private void storeNewBindingKeys(ArrayList<String> existingBindingsData, List<Binding> AMQPBindingObjectList){
251+
// comparing with the stored key and adding the new binding key into the mongoDB.
252+
for(final Binding bindingKey:AMQPBindingObjectList){
253+
if(existingBindingsData.contains(bindingKey.getRoutingKey())){
254+
LOGGER.info("Binding already present in mongoDB");
255+
}else{
256+
BasicDBObject document = new BasicDBObject();
257+
document.put("destination",bindingKey.getDestination());
258+
document.put("destinationType", bindingKey.getDestinationType().toString());
259+
document.put("exchange", bindingKey.getExchange());
260+
document.put("bindingKeys", bindingKey.getRoutingKey());
261+
document.put("arg", bindingKey.getArguments().toString());
262+
mongoDBHandler.insertDocument(dataBaseName, collectionName, document.toString());
263+
}
264+
}
265+
}
266+
183267
@Bean
184268
public SimpleMessageListenerContainer bindToQueueForRecentEvents(
185269
final ConnectionFactory springConnectionFactory,

src/main/resources/application.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ subscription.collection.name: subscription
8181
# name of the collection where we store pair of subscription:aggregated
8282
# object where notification has been done and should not be repeated
8383
subscription.collection.repeatFlagHandlerName: subscription_repeat_handler
84+
# name of the collection where binding keys are stored
85+
bindingkeys.collection.name: binding_keys
8486

8587
# Need to be set to True to use Test Rules page in EI-Frontend.
8688
# This is when you want to define new aggregation rules and test it

0 commit comments

Comments
 (0)