ARTEMIS-1575 configure custom broker plugins with key/value properties.
The properties are read and passed into the the broker plugin's init(Map<String,String>)
This commit is contained in:
parent
1ef8199f23
commit
d95757057e
|
@ -703,6 +703,8 @@ public final class FileConfigurationParser extends XMLConfigurationUtil {
|
||||||
private ActiveMQServerPlugin parseActiveMQServerPlugin(Node item) {
|
private ActiveMQServerPlugin parseActiveMQServerPlugin(Node item) {
|
||||||
final String clazz = item.getAttributes().getNamedItem("class-name").getNodeValue();
|
final String clazz = item.getAttributes().getNamedItem("class-name").getNodeValue();
|
||||||
|
|
||||||
|
Map<String, String> properties = getMapOfChildPropertyElements(item);
|
||||||
|
|
||||||
ActiveMQServerPlugin serverPlugin = AccessController.doPrivileged(new PrivilegedAction<ActiveMQServerPlugin>() {
|
ActiveMQServerPlugin serverPlugin = AccessController.doPrivileged(new PrivilegedAction<ActiveMQServerPlugin>() {
|
||||||
@Override
|
@Override
|
||||||
public ActiveMQServerPlugin run() {
|
public ActiveMQServerPlugin run() {
|
||||||
|
@ -710,9 +712,25 @@ public final class FileConfigurationParser extends XMLConfigurationUtil {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
serverPlugin.init(properties);
|
||||||
|
|
||||||
return serverPlugin;
|
return serverPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getMapOfChildPropertyElements(Node item) {
|
||||||
|
Map<String, String> properties = new HashMap<>();
|
||||||
|
NodeList children = item.getChildNodes();
|
||||||
|
for (int i = 0; i < children.getLength(); i++) {
|
||||||
|
Node child = children.item(i);
|
||||||
|
if (child.getNodeName().equals("property")) {
|
||||||
|
String key = getAttributeValue(child, "key");
|
||||||
|
String value = getAttributeValue(child, "value");
|
||||||
|
properties.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param e
|
* @param e
|
||||||
* @param config
|
* @param config
|
||||||
|
@ -1656,16 +1674,7 @@ public final class FileConfigurationParser extends XMLConfigurationUtil {
|
||||||
Element element = (Element) node;
|
Element element = (Element) node;
|
||||||
String className = getString(element, "class-name", null, Validators.NO_CHECK);
|
String className = getString(element, "class-name", null, Validators.NO_CHECK);
|
||||||
|
|
||||||
Map<String, String> properties = new HashMap<>();
|
Map<String, String> properties = getMapOfChildPropertyElements(element);
|
||||||
NodeList children = element.getChildNodes();
|
|
||||||
for (int j = 0; j < children.getLength(); j++) {
|
|
||||||
Node child = children.item(j);
|
|
||||||
if (child.getNodeName().equals("property")) {
|
|
||||||
String key = getAttributeValue(child, "key");
|
|
||||||
String value = getAttributeValue(child, "value");
|
|
||||||
properties.put(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new TransformerConfiguration(className).setProperties(properties);
|
return new TransformerConfiguration(className).setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -460,4 +460,11 @@ public interface ActiveMQServerPlugin {
|
||||||
default void criticalFailure(CriticalComponent components) throws ActiveMQException {
|
default void criticalFailure(CriticalComponent components) throws ActiveMQException {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used to pass configured properties to Plugin
|
||||||
|
*
|
||||||
|
* @param properties
|
||||||
|
*/
|
||||||
|
default void init(Map<String, String> properties) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -934,6 +934,15 @@
|
||||||
a broker plugin
|
a broker plugin
|
||||||
</xsd:documentation>
|
</xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element ref="property" maxOccurs="unbounded" minOccurs="0">
|
||||||
|
<xsd:annotation>
|
||||||
|
<xsd:documentation>
|
||||||
|
properties to configure a plugin
|
||||||
|
</xsd:documentation>
|
||||||
|
</xsd:annotation>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:sequence>
|
||||||
<xsd:attribute name="class-name" type="xsd:string" use="required">
|
<xsd:attribute name="class-name" type="xsd:string" use="required">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation>
|
<xsd:documentation>
|
||||||
|
@ -1443,7 +1452,7 @@
|
||||||
</xsd:documentation>
|
</xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
</xsd:element>
|
</xsd:element>
|
||||||
<xsd:element name="property" type="transformerProperty" maxOccurs="unbounded" minOccurs="0">
|
<xsd:element ref="property" maxOccurs="unbounded" minOccurs="0">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation>
|
<xsd:documentation>
|
||||||
properties to configure the transformer class
|
properties to configure the transformer class
|
||||||
|
@ -1453,23 +1462,24 @@
|
||||||
</xsd:sequence>
|
</xsd:sequence>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
|
||||||
|
<xsd:element name="property">
|
||||||
<xsd:complexType name="transformerProperty">
|
<xsd:complexType>
|
||||||
<xsd:attribute name="key" type="xsd:string" use="required">
|
<xsd:attribute name="key" type="xsd:string" use="required">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation>
|
<xsd:documentation>
|
||||||
key for the property
|
key for the property
|
||||||
</xsd:documentation>
|
</xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
</xsd:attribute>
|
</xsd:attribute>
|
||||||
<xsd:attribute name="value" type="xsd:string" use="required">
|
<xsd:attribute name="value" type="xsd:string" use="required">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation>
|
<xsd:documentation>
|
||||||
value for the property
|
value for the property
|
||||||
</xsd:documentation>
|
</xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
</xsd:attribute>
|
</xsd:attribute>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
|
||||||
|
|
||||||
<!-- CLUSTER CONNECTION CONFIGURATION -->
|
<!-- CLUSTER CONNECTION CONFIGURATION -->
|
||||||
|
|
|
@ -20,7 +20,11 @@
|
||||||
xsi:schemaLocation="urn:activemq ../../../../activemq-server/src/main/resources/schema/artemis-server.xsd">
|
xsi:schemaLocation="urn:activemq ../../../../activemq-server/src/main/resources/schema/artemis-server.xsd">
|
||||||
<core xmlns="urn:activemq:core">
|
<core xmlns="urn:activemq:core">
|
||||||
<broker-plugins>
|
<broker-plugins>
|
||||||
<broker-plugin class-name="org.apache.activemq.artemis.core.config.impl.FileConfigurationTest$EmptyPlugin1" />
|
<broker-plugin class-name="org.apache.activemq.artemis.core.config.impl.FileConfigurationTest$EmptyPlugin1">
|
||||||
|
<property key="key1" value="value1"/>
|
||||||
|
<property key="key2" value="value2"/>
|
||||||
|
<property key="key3" value="value3"/>
|
||||||
|
</broker-plugin>
|
||||||
<broker-plugin class-name="org.apache.activemq.artemis.core.config.impl.FileConfigurationTest$EmptyPlugin2" />
|
<broker-plugin class-name="org.apache.activemq.artemis.core.config.impl.FileConfigurationTest$EmptyPlugin2" />
|
||||||
</broker-plugins>
|
</broker-plugins>
|
||||||
</core>
|
</core>
|
||||||
|
|
|
@ -1271,7 +1271,7 @@
|
||||||
</xsd:documentation>
|
</xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
</xsd:element>
|
</xsd:element>
|
||||||
<xsd:element name="property" type="transformerProperty" maxOccurs="unbounded" minOccurs="0">
|
<xsd:element ref="property" maxOccurs="unbounded" minOccurs="0">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation>
|
<xsd:documentation>
|
||||||
properties to configure the transformer class
|
properties to configure the transformer class
|
||||||
|
@ -1281,23 +1281,24 @@
|
||||||
</xsd:sequence>
|
</xsd:sequence>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
|
||||||
|
<xsd:element name="property">
|
||||||
<xsd:complexType name="transformerProperty">
|
<xsd:complexType>
|
||||||
<xsd:attribute name="key" type="xsd:string" use="required">
|
<xsd:attribute name="key" type="xsd:string" use="required">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation>
|
<xsd:documentation>
|
||||||
key for the property
|
key for the property
|
||||||
</xsd:documentation>
|
</xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
</xsd:attribute>
|
</xsd:attribute>
|
||||||
<xsd:attribute name="value" type="xsd:string" use="required">
|
<xsd:attribute name="value" type="xsd:string" use="required">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation>
|
<xsd:documentation>
|
||||||
value for the property
|
value for the property
|
||||||
</xsd:documentation>
|
</xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
</xsd:attribute>
|
</xsd:attribute>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
|
||||||
|
|
||||||
<!-- CLUSTER CONNECTION CONFIGURATION -->
|
<!-- CLUSTER CONNECTION CONFIGURATION -->
|
||||||
|
|
|
@ -16,14 +16,20 @@ If you are using an embed system than you will need the jar under the regular cl
|
||||||
|
|
||||||
## Registering a Plugin
|
## Registering a Plugin
|
||||||
|
|
||||||
To register a plugin with by XML you need to add the `broker-plugins` element at the `broker.xml`.
|
To register a plugin with by XML you need to add the `broker-plugins` element at the `broker.xml`. It is also possible
|
||||||
|
to pass configuration to a plugin using the `property` child element(s). These properties (zero to many)
|
||||||
|
will be read and passed into the Plugin's `init(Map<String, String>)` operation after the plugin
|
||||||
|
has been instantiated.
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<configuration ...>
|
<configuration ...>
|
||||||
|
|
||||||
...
|
...
|
||||||
<broker-plugins>
|
<broker-plugins>
|
||||||
<broker-plugin class-name="some.plugin.UserPlugin" />
|
<broker-plugin class-name="some.plugin.UserPlugin">
|
||||||
|
<property key="property1" value="val_1" />
|
||||||
|
<property key="property2" value="val_2" />
|
||||||
|
</broker-plugin>
|
||||||
</broker-plugins>
|
</broker-plugins>
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with this
|
||||||
|
* work for additional information regarding copyright ownership. The ASF
|
||||||
|
* licenses this file to You under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package org.apache.activemq.artemis.tests.integration.plugin;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import org.apache.activemq.artemis.api.core.ActiveMQException;
|
||||||
|
import org.apache.activemq.artemis.api.core.Message;
|
||||||
|
import org.apache.activemq.artemis.core.postoffice.RoutingStatus;
|
||||||
|
import org.apache.activemq.artemis.core.server.ServerSession;
|
||||||
|
import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerPlugin;
|
||||||
|
import org.apache.activemq.artemis.core.transaction.Transaction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in tests to verify configuration passed into plugin correctly.
|
||||||
|
*/
|
||||||
|
public class ConfigurationVerifier implements ActiveMQServerPlugin, Serializable {
|
||||||
|
|
||||||
|
public static final String PROPERTY1 = "property1";
|
||||||
|
public static final String PROPERTY2 = "property2";
|
||||||
|
public static final String PROPERTY3 = "property3";
|
||||||
|
|
||||||
|
public String value1;
|
||||||
|
public String value2;
|
||||||
|
public String value3;
|
||||||
|
public AtomicInteger afterSendCounter = new AtomicInteger();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Map<String, String> properties) {
|
||||||
|
value1 = properties.get(PROPERTY1);
|
||||||
|
value2 = properties.get(PROPERTY2);
|
||||||
|
value3 = properties.get(PROPERTY3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to ensure the plugin is being invoked
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void afterSend(ServerSession session,
|
||||||
|
Transaction tx,
|
||||||
|
Message message,
|
||||||
|
boolean direct,
|
||||||
|
boolean noAutoCreateQueue,
|
||||||
|
RoutingStatus result) throws ActiveMQException {
|
||||||
|
afterSendCounter.incrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -76,12 +76,17 @@ public class CorePluginTest extends JMSTestBase {
|
||||||
|
|
||||||
private final Map<String, AtomicInteger> methodCalls = new HashMap<>();
|
private final Map<String, AtomicInteger> methodCalls = new HashMap<>();
|
||||||
private final MethodCalledVerifier verifier = new MethodCalledVerifier(methodCalls);
|
private final MethodCalledVerifier verifier = new MethodCalledVerifier(methodCalls);
|
||||||
|
private final ConfigurationVerifier configurationVerifier = new ConfigurationVerifier();
|
||||||
public static final String INVM_CONNECTOR_FACTORY = InVMConnectorFactory.class.getCanonicalName();
|
public static final String INVM_CONNECTOR_FACTORY = InVMConnectorFactory.class.getCanonicalName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Configuration createDefaultConfig(boolean netty) throws Exception {
|
protected Configuration createDefaultConfig(boolean netty) throws Exception {
|
||||||
Configuration config = super.createDefaultConfig(netty);
|
Configuration config = super.createDefaultConfig(netty);
|
||||||
config.registerBrokerPlugin(verifier);
|
config.registerBrokerPlugin(verifier);
|
||||||
|
Map<String, String> props = new HashMap<>(1);
|
||||||
|
props.put(ConfigurationVerifier.PROPERTY1, "val_1");
|
||||||
|
configurationVerifier.init(props);
|
||||||
|
config.registerBrokerPlugin(configurationVerifier);
|
||||||
config.setMessageExpiryScanPeriod(0); // disable expiry scan so it's alwyas through delivery
|
config.setMessageExpiryScanPeriod(0); // disable expiry scan so it's alwyas through delivery
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
@ -118,6 +123,9 @@ public class CorePluginTest extends JMSTestBase {
|
||||||
AFTER_MESSAGE_ROUTE);
|
AFTER_MESSAGE_ROUTE);
|
||||||
verifier.validatePluginMethodsEquals(2, BEFORE_CREATE_SESSION, AFTER_CREATE_SESSION, BEFORE_CLOSE_SESSION,
|
verifier.validatePluginMethodsEquals(2, BEFORE_CREATE_SESSION, AFTER_CREATE_SESSION, BEFORE_CLOSE_SESSION,
|
||||||
AFTER_CLOSE_SESSION);
|
AFTER_CLOSE_SESSION);
|
||||||
|
|
||||||
|
assertEquals("configurationVerifier is invoked", 1, configurationVerifier.afterSendCounter.get());
|
||||||
|
assertEquals("configurationVerifier config set", "val_1", configurationVerifier.value1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -38,8 +38,13 @@ public class XmlConfigPluginTest extends ActiveMQTestBase {
|
||||||
ActiveMQServer server = addServer(new ActiveMQServerImpl(fc));
|
ActiveMQServer server = addServer(new ActiveMQServerImpl(fc));
|
||||||
try {
|
try {
|
||||||
server.start();
|
server.start();
|
||||||
assertEquals(1, server.getBrokerPlugins().size());
|
assertEquals(2, server.getBrokerPlugins().size());
|
||||||
assertTrue(server.getBrokerPlugins().get(0) instanceof MethodCalledVerifier);
|
assertTrue(server.getBrokerPlugins().get(0) instanceof MethodCalledVerifier);
|
||||||
|
assertTrue(server.getBrokerPlugins().get(1) instanceof ConfigurationVerifier);
|
||||||
|
ConfigurationVerifier configurationVerifier = (ConfigurationVerifier) server.getBrokerPlugins().get(1);
|
||||||
|
assertEquals("value1", "val_1", configurationVerifier.value1);
|
||||||
|
assertEquals("value2", "val_2", configurationVerifier.value2);
|
||||||
|
assertNull("value3 should not have been set", configurationVerifier.value3);
|
||||||
} finally {
|
} finally {
|
||||||
if (server != null) {
|
if (server != null) {
|
||||||
server.stop();
|
server.stop();
|
||||||
|
|
|
@ -42,6 +42,10 @@
|
||||||
|
|
||||||
<broker-plugins>
|
<broker-plugins>
|
||||||
<broker-plugin class-name="org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier" />
|
<broker-plugin class-name="org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier" />
|
||||||
|
<broker-plugin class-name="org.apache.activemq.artemis.tests.integration.plugin.ConfigurationVerifier">
|
||||||
|
<property key="property1" value="val_1"/>
|
||||||
|
<property key="property2" value="val_2"/>
|
||||||
|
</broker-plugin>
|
||||||
</broker-plugins>
|
</broker-plugins>
|
||||||
</core>
|
</core>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue