Skip to content

Commit 9fe80fe

Browse files
committed
ARTEMIS-5871 make it illegal to provide non xml reloadable config and a properties source when reload is enabled
1 parent f942564 commit 9fe80fe

4 files changed

Lines changed: 77 additions & 14 deletions

File tree

artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ public class ActiveMQServerImpl implements ActiveMQServer {
308308
protected volatile ExecutorFactory ioExecutorFactory;
309309

310310
/**
311-
* This is a thread pool for page only tasks only. This is because we have to limit parallel reads on paging.
311+
* This is a thread pool for page tasks only. This is because we have to limit parallel reads on paging.
312312
*/
313313
protected volatile ExecutorFactory pageExecutorFactory;
314314

@@ -679,8 +679,18 @@ public CriticalAnalyzer getCriticalAnalyzer() {
679679
}
680680

681681
@Override
682-
public void setProperties(String fileUrltoBrokerProperties) {
683-
propertiesFileUrl = fileUrltoBrokerProperties;
682+
public void setProperties(String fileUrlToBrokerProperties) {
683+
throwIfReloadableConfigProvidedWithoutFileAndBrokerPropertiesUrlNonNullAndReload(configuration, fileUrlToBrokerProperties);
684+
propertiesFileUrl = fileUrlToBrokerProperties;
685+
}
686+
687+
private void throwIfReloadableConfigProvidedWithoutFileAndBrokerPropertiesUrlNonNullAndReload(Configuration configuration, String propertiesFileUrl) {
688+
if (configuration.getConfigurationUrl() == null && configuration.getConfigurationFileRefreshPeriod() > 0 && configuration.resolvePropertiesSources(propertiesFileUrl) != null) {
689+
// if any non xml (programmatic) provided config is reloadable, on the first properties source reload it will whack that config as the reload has the source of truth for reloadable attributes
690+
if (hasReloadableConfig(configuration)) {
691+
throw new IllegalStateException(String.format("a properties source (%s) is illegal, programmatic config contains reloadable elements and configurationFileRefreshPeriod > 0; your programmatic config will be replaced on reload of the properties source", propertiesFileUrl));
692+
}
693+
}
684694
}
685695

686696
@Override
@@ -4689,8 +4699,16 @@ private void reloadConfigurationFile(URL xmlConfigUri) throws Exception {
46894699
legacyJMSConfiguration.parseConfiguration(xmlConfigUri.openStream());
46904700
}
46914701
config.parseProperties(propertiesFileUrl);
4692-
configuration.setStatus(config.getStatus());
4702+
updateReloadableConfigurationFrom(config);
4703+
updateStatus(ServerStatus.CONFIGURATION_COMPONENT, configuration.getStatus());
4704+
configurationReloadDeployed.set(false);
4705+
if (isActive()) {
4706+
deployReloadableConfigFromConfiguration();
4707+
}
4708+
}
46934709

4710+
private void updateReloadableConfigurationFrom(Configuration config) {
4711+
configuration.setStatus(config.getStatus());
46944712
configuration.setSecurityRoles(config.getSecurityRoles());
46954713
configuration.setAddressSettings(config.getAddressSettings());
46964714
configuration.setDivertConfigurations(config.getDivertConfigurations());
@@ -4701,14 +4719,22 @@ private void reloadConfigurationFile(URL xmlConfigUri) throws Exception {
47014719
configuration.setAcceptorConfigurations(config.getAcceptorConfigurations());
47024720
configuration.setAMQPConnectionConfigurations(config.getAMQPConnection());
47034721
configuration.setPurgePageFolders(config.isPurgePageFolders());
4704-
configuration.setConnectionRouters(config.getConnectionRouters()); // needs reload logic
4722+
configuration.setConnectionRouters(config.getConnectionRouters());
47054723
configuration.setJaasConfigs(config.getJaasConfigs());
4724+
}
47064725

4707-
updateStatus(ServerStatus.CONFIGURATION_COMPONENT, configuration.getStatus());
4708-
configurationReloadDeployed.set(false);
4709-
if (isActive()) {
4710-
deployReloadableConfigFromConfiguration();
4711-
}
4726+
private static boolean hasReloadableConfig(Configuration configuration) {
4727+
return !configuration.getSecurityRoles().isEmpty() ||
4728+
!configuration.getAddressSettings().isEmpty() ||
4729+
!configuration.getDivertConfigurations().isEmpty() ||
4730+
!configuration.getAddressConfigurations().isEmpty() ||
4731+
!configuration.getQueueConfigs().isEmpty() ||
4732+
!configuration.getBridgeConfigurations().isEmpty() ||
4733+
!configuration.getConnectorConfigurations().isEmpty() ||
4734+
!configuration.getAcceptorConfigurations().isEmpty() ||
4735+
!configuration.getAMQPConnection().isEmpty() ||
4736+
!configuration.getConnectionRouters().isEmpty() ||
4737+
!configuration.getJaasConfigs().isEmpty();
47124738
}
47134739

47144740
private void deployReloadableConfigFromConfiguration() throws Exception {

docs/user-manual/config-reload.adoc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,4 +544,7 @@ Adding, updating and removing an `<acceptor>` is supported, updating or removing
544544
=== `<queues>` _(Deprecated)_
545545

546546
== Broker Properties
547-
The location of xref:configuration-index.adoc#broker-properties[brokerProperties] files will be tracked for reload. Any property values that relfect reloadable parameters will take effect after the `configuration-file-refresh-period`.
547+
The location of xref:configuration-index.adoc#broker-properties[brokerProperties] files will be tracked for reload. Any property values that reflect reloadable parameters will take effect after the `configuration-file-refresh-period`.
548+
549+
[NOTE]
550+
If programmatic configuration is in play, any configuration object passed to the broker must not contain reloadable config *and* have a broker properties source. The broker does not have any config reload callbacks at this time to protect the programmatic configuration. An IllegalStateException will be thrown if this arises.

tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/routing/ElasticQueueTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ private void prepareNodesAndStartCombinedHeadTail() throws Exception {
427427
.setAutoDeleteQueues(false).setAutoDeleteAddresses(false); // so slow consumer can kick in!
428428

429429
Configuration baseConfig = new ConfigurationImpl();
430+
baseConfig.setConfigurationFileRefreshPeriod(-1); // the classpath has broker.properties we don't want to reload
430431
baseConfig.getAddressSettings().put(qName, blockingQueue);
431432

432433
ConnectionRouterConfiguration connectionRouterConfiguration = new ConnectionRouterConfiguration();

tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/server/ConfigurationTest.java

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import static org.junit.jupiter.api.Assertions.assertEquals;
4646
import static org.junit.jupiter.api.Assertions.assertNotEquals;
4747
import static org.junit.jupiter.api.Assertions.assertNotNull;
48+
import static org.junit.jupiter.api.Assertions.assertThrows;
4849
import static org.junit.jupiter.api.Assertions.assertTrue;
4950

5051
public class ConfigurationTest extends ActiveMQTestBase {
@@ -195,20 +196,21 @@ public void testPropertiesOnlyConfigReload() throws Exception {
195196
properties.store(outStream, null);
196197
}
197198
assertTrue(propsFile.exists());
198-
properties.clear();
199199

200200
FileConfiguration fc = new FileConfiguration();
201201
ActiveMQJAASSecurityManager sm = new ActiveMQJAASSecurityManager(InVMLoginModule.class.getName(), new SecurityConfiguration());
202202
ActiveMQServer server = addServer(new ActiveMQServerImpl(fc, sm));
203203
server.setProperties(propsFile.getAbsolutePath()); // no xml config
204204
try {
205-
206205
server.start();
207206

208207
assertEquals(1, server.getConfiguration().getConnectionRouters().size());
209208
assertEquals("LF", server.getConfiguration().getConnectionRouters().get(0).getLocalTargetFilter());
210209
assertEquals(1, server.getActiveMQServerControl().getAcceptors().length);
211-
// verify update
210+
assertEquals(100, server.getConfiguration().getConfigurationFileRefreshPeriod());
211+
212+
// verify update and remove of tcp acceptor
213+
properties.clear();
212214
properties.put("configurationFileRefreshPeriod", "100");
213215
properties.put("persistenceEnabled", "false");
214216
properties.put("connectionRouters.joe.localTargetFilter", "UPDATED");
@@ -222,6 +224,8 @@ public void testPropertiesOnlyConfigReload() throws Exception {
222224
return "UPDATED".equals(server.getConfiguration().getConnectionRouters().get(0).getLocalTargetFilter());
223225
});
224226

227+
// no change
228+
assertEquals(100, server.getConfiguration().getConfigurationFileRefreshPeriod());
225229
// verify remove
226230
assertEquals(0, server.getActiveMQServerControl().getAcceptors().length);
227231

@@ -373,6 +377,35 @@ public void testPropertiesDirWithFilterConfigReloadOnNewFileAfterGettingJournalL
373377
}
374378
}
375379

380+
@Test
381+
public void testPropertiesAndProgrammaticReloadableConfigArg() throws Exception {
382+
383+
File propsFile = new File(getTestDirfile(), "somemore.props");
384+
propsFile.createNewFile();
385+
386+
387+
Properties properties = new ConfigurationImpl.InsertionOrderedProperties();
388+
properties.put("configurationFileRefreshPeriod", "100");
389+
properties.put("persistenceEnabled", "false");
390+
properties.put("acceptorConfigurations.reloadable.factoryClassName", NETTY_ACCEPTOR_FACTORY);
391+
properties.put("acceptorConfigurations.reloadable.params.HOST", "LOCALHOST");
392+
properties.put("acceptorConfigurations.reloadable.params.PORT", "61616");
393+
394+
try (FileOutputStream outStream = new FileOutputStream(propsFile)) {
395+
properties.store(outStream, null);
396+
}
397+
assertTrue(propsFile.exists());
398+
399+
ConfigurationImpl programmatic = new ConfigurationImpl();
400+
programmatic.addAcceptorConfiguration("tcp", "tcp://localhost:62618");
401+
ActiveMQJAASSecurityManager sm = new ActiveMQJAASSecurityManager(InVMLoginModule.class.getName(), new SecurityConfiguration());
402+
ActiveMQServer server = addServer(new ActiveMQServerImpl(programmatic, sm));
403+
404+
assertThrows(IllegalStateException.class, () -> {
405+
server.setProperties(propsFile.getAbsolutePath());
406+
});
407+
}
408+
376409
protected ActiveMQServer getActiveMQServer(String brokerConfig) throws Exception {
377410
FileConfiguration fc = new FileConfiguration();
378411
FileJMSConfiguration fileConfiguration = new FileJMSConfiguration();

0 commit comments

Comments
 (0)