fix: #2428 - recovery manual declarables without application context (#2429)

* fix: recovery manual declaration without application context

* test: recovery manual declaration without application context
This commit is contained in:
EldarErel
2023-03-22 19:34:48 +02:00
committed by GitHub
parent a5d8e36a49
commit 6d91c90fe4
2 changed files with 56 additions and 1 deletions

View File

@@ -638,6 +638,8 @@ public class RabbitAdmin implements AmqpAdmin, ApplicationContextAware, Applicat
@Override // NOSONAR complexity
public void initialize() {
redeclareManualDeclarables();
if (this.applicationContext == null) {
this.logger.debug("no ApplicationContext has been set, cannot auto-declare Exchanges, Queues, and Bindings");
return;
@@ -690,6 +692,14 @@ public class RabbitAdmin implements AmqpAdmin, ApplicationContextAware, Applicat
declareBindings(channel, bindings.toArray(new Binding[bindings.size()]));
return null;
});
this.logger.debug("Declarations finished");
}
/**
* Process manual declarables.
*/
private void redeclareManualDeclarables() {
if (this.manualDeclarables.size() > 0) {
synchronized (this.manualDeclarables) {
this.logger.debug("Redeclaring manually declared Declarables");
@@ -706,7 +716,6 @@ public class RabbitAdmin implements AmqpAdmin, ApplicationContextAware, Applicat
}
}
}
this.logger.debug("Declarations finished");
}

View File

@@ -445,6 +445,52 @@ public class RabbitAdminTests extends NeedsManagementTests {
cf.destroy();
}
@Test
void manualDeclarationsWithoutApplicationContext() {
CachingConnectionFactory cf = new CachingConnectionFactory(
RabbitAvailableCondition.getBrokerRunning().getConnectionFactory());
RabbitAdmin admin = new RabbitAdmin(cf);
admin.setRedeclareManualDeclarations(true);
Map<?, ?> declarables = TestUtils.getPropertyValue(admin, "manualDeclarables", Map.class);
assertThat(declarables).hasSize(0);
RabbitTemplate template = new RabbitTemplate(cf);
// manual declarations
admin.declareQueue(new Queue("test1", false, true, true));
admin.declareQueue(new Queue("test2", false, true, true));
admin.declareExchange(new DirectExchange("ex1", false, true));
admin.declareBinding(new Binding("test1", DestinationType.QUEUE, "ex1", "test", null));
admin.deleteQueue("test2");
template.execute(chan -> chan.queueDelete("test1"));
cf.resetConnection();
admin.initialize();
assertThat(admin.getQueueProperties("test1")).isNotNull();
assertThat(admin.getQueueProperties("test2")).isNull();
assertThat(declarables).hasSize(3);
// verify the exchange and binding were recovered too
template.convertAndSend("ex1", "test", "foo");
Object received = template.receiveAndConvert("test1", 5000);
assertThat(received).isEqualTo("foo");
admin.resetAllManualDeclarations();
assertThat(declarables).hasSize(0);
cf.resetConnection();
admin.initialize();
assertThat(admin.getQueueProperties("test1")).isNull();
admin.declareQueue(new Queue("test1", false, true, true));
admin.declareExchange(new DirectExchange("ex1", false, true));
admin.declareBinding(new Binding("test1", DestinationType.QUEUE, "ex1", "test", null));
admin.declareExchange(new DirectExchange("ex2", false, true));
admin.declareBinding(new Binding("test1", DestinationType.QUEUE, "ex2", "test", null));
admin.declareBinding(new Binding("ex1", DestinationType.EXCHANGE, "ex2", "ex1", null));
assertThat(declarables).hasSize(6);
admin.deleteExchange("ex2");
assertThat(declarables).hasSize(3);
admin.deleteQueue("test1");
assertThat(declarables).hasSize(1);
admin.deleteExchange("ex1");
assertThat(declarables).hasSize(0);
cf.destroy();
}
@Configuration
public static class Config {