ARTEMIS-3074 Add ActiveMQServerControl#createBridge() method variant accepting a JSON string
This commit is contained in:
parent
bd738e0e00
commit
ebeea15c2a
|
@ -1679,6 +1679,10 @@ public interface ActiveMQServerControl {
|
|||
@Attribute(desc = "Names of the bridges deployed on this server")
|
||||
String[] getBridgeNames();
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in favour of {@link #createBridge(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Operation(desc = "Create a Bridge", impact = MBeanOperationInfo.ACTION)
|
||||
void createBridge(@Parameter(name = "name", desc = "Name of the bridge") String name,
|
||||
@Parameter(name = "queueName", desc = "Name of the source queue") String queueName,
|
||||
|
@ -1699,6 +1703,10 @@ public interface ActiveMQServerControl {
|
|||
@Parameter(name = "user", desc = "User name") String user,
|
||||
@Parameter(name = "password", desc = "User password") String password) throws Exception;
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in favour of {@link #createBridge(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Operation(desc = "Create a Bridge", impact = MBeanOperationInfo.ACTION)
|
||||
void createBridge(@Parameter(name = "name", desc = "Name of the bridge") String name,
|
||||
@Parameter(name = "queueName", desc = "Name of the source queue") String queueName,
|
||||
|
@ -1720,6 +1728,10 @@ public interface ActiveMQServerControl {
|
|||
@Parameter(name = "user", desc = "User name") String user,
|
||||
@Parameter(name = "password", desc = "User password") String password) throws Exception;
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in favour of {@link #createBridge(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Operation(desc = "Create a Bridge", impact = MBeanOperationInfo.ACTION)
|
||||
void createBridge(@Parameter(name = "name", desc = "Name of the bridge") String name,
|
||||
@Parameter(name = "queueName", desc = "Name of the source queue") String queueName,
|
||||
|
@ -1741,6 +1753,10 @@ public interface ActiveMQServerControl {
|
|||
@Parameter(name = "user", desc = "User name") String user,
|
||||
@Parameter(name = "password", desc = "User password") String password) throws Exception;
|
||||
|
||||
/**
|
||||
* @deprecated Deprecated in favour of {@link #createBridge(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Operation(desc = "Create a Bridge", impact = MBeanOperationInfo.ACTION)
|
||||
void createBridge(@Parameter(name = "name", desc = "Name of the bridge") String name,
|
||||
@Parameter(name = "queueName", desc = "Name of the source queue") String queueName,
|
||||
|
@ -1760,6 +1776,14 @@ public interface ActiveMQServerControl {
|
|||
@Parameter(name = "user", desc = "User name") String user,
|
||||
@Parameter(name = "password", desc = "User password") String password) throws Exception;
|
||||
|
||||
/**
|
||||
* Create a bridge.
|
||||
*
|
||||
* @param bridgeConfiguration the configuration of the queue in JSON format
|
||||
*/
|
||||
@Operation(desc = "Create a bridge", impact = MBeanOperationInfo.ACTION)
|
||||
void createBridge(@Parameter(name = "bridgeConfiguration", desc = "the configuration of the bridge in JSON format") String bridgeConfiguration) throws Exception;
|
||||
|
||||
@Operation(desc = "Destroy a bridge", impact = MBeanOperationInfo.ACTION)
|
||||
void destroyBridge(@Parameter(name = "name", desc = "Name of the bridge") String name) throws Exception;
|
||||
|
||||
|
|
|
@ -16,7 +16,13 @@
|
|||
*/
|
||||
package org.apache.activemq.artemis.core.config;
|
||||
|
||||
import org.apache.activemq.artemis.utils.JsonLoader;
|
||||
|
||||
import javax.json.JsonObject;
|
||||
import javax.json.JsonString;
|
||||
import javax.json.JsonValue;
|
||||
import java.io.Serializable;
|
||||
import java.io.StringReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -24,8 +30,10 @@ public final class TransformerConfiguration implements Serializable {
|
|||
|
||||
private static final long serialVersionUID = -1057244274380572226L;
|
||||
|
||||
private final String className;
|
||||
public static final String CLASS_NAME = "class-name";
|
||||
public static final String PROPERTIES = "properties";
|
||||
|
||||
private final String className;
|
||||
private Map<String, String> properties = new HashMap<>();
|
||||
|
||||
public TransformerConfiguration(String className) {
|
||||
|
@ -40,6 +48,43 @@ public final class TransformerConfiguration implements Serializable {
|
|||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a {@code TransformerConfiguration} created from the JSON-formatted input {@code String}.
|
||||
* The input should contain these entries:
|
||||
*
|
||||
* <p><ul>
|
||||
* <li>class-name - a string value,
|
||||
* <li>properties - an object containing string key-value pairs.
|
||||
* </ul></p>
|
||||
*
|
||||
* @param jsonString json string
|
||||
* @return the {@code TransformerConfiguration} created from the JSON-formatted input {@code String}
|
||||
*/
|
||||
public static TransformerConfiguration fromJSON(String jsonString) {
|
||||
JsonObject json = JsonLoader.readObject(new StringReader(jsonString));
|
||||
|
||||
// name is the only required value
|
||||
if (!json.containsKey(CLASS_NAME)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
TransformerConfiguration result = new TransformerConfiguration(json.getString(CLASS_NAME));
|
||||
|
||||
if (json.containsKey(PROPERTIES)) {
|
||||
HashMap<String, String> properties = new HashMap<>();
|
||||
for (Map.Entry<String, JsonValue> propEntry: json.getJsonObject(PROPERTIES).entrySet()) {
|
||||
if (propEntry.getValue().getValueType() == JsonValue.ValueType.STRING) {
|
||||
properties.put(propEntry.getKey(), ((JsonString) propEntry.getValue()).getString());
|
||||
} else {
|
||||
properties.put(propEntry.getKey(), propEntry.getValue().toString());
|
||||
}
|
||||
}
|
||||
result.setProperties(properties);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param properties the properties to set
|
||||
*/
|
||||
|
|
|
@ -16,17 +16,51 @@
|
|||
*/
|
||||
package org.apache.activemq.artemis.core.config;
|
||||
|
||||
import javax.json.JsonArrayBuilder;
|
||||
import javax.json.JsonObject;
|
||||
import javax.json.JsonObjectBuilder;
|
||||
import javax.json.JsonString;
|
||||
import javax.json.JsonValue;
|
||||
import java.io.Serializable;
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
|
||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
|
||||
import org.apache.activemq.artemis.core.server.ComponentConfigurationRoutingType;
|
||||
import org.apache.activemq.artemis.utils.JsonLoader;
|
||||
|
||||
public final class BridgeConfiguration implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1057244274380572226L;
|
||||
|
||||
public static String NAME = "name";
|
||||
public static String QUEUE_NAME = "queue-name";
|
||||
public static String FORWARDING_ADDRESS = "forwarding-address";
|
||||
public static String FILTER_STRING = "filter-string";
|
||||
public static String STATIC_CONNECTORS = "static-connectors";
|
||||
public static String DISCOVERY_GROUP_NAME = "discovery-group-name";
|
||||
public static String HA = "ha";
|
||||
public static String TRANSFORMER_CONFIGURATION = "transformer-configuration";
|
||||
public static String RETRY_INTERVAL = "retry-interval";
|
||||
public static String RETRY_INTERVAL_MULTIPLIER = "retry-interval-multiplier";
|
||||
public static String INITIAL_CONNECT_ATTEMPTS = "initial-connect-attempts";
|
||||
public static String RECONNECT_ATTEMPTS = "reconnect-attempts";
|
||||
public static String RECONNECT_ATTEMPTS_ON_SAME_NODE = "reconnect-attempts-on-same-node";
|
||||
public static String USE_DUPLICATE_DETECTION = "use-duplicate-detection";
|
||||
public static String CONFIRMATION_WINDOW_SIZE = "confirmation-window-size";
|
||||
public static String PRODUCER_WINDOW_SIZE = "producer-window-size";
|
||||
public static String CLIENT_FAILURE_CHECK_PERIOD = "client-failure-check-period";
|
||||
public static String USER = "user";
|
||||
public static String PASSWORD = "password";
|
||||
public static String CONNECTION_TTL = "connection-ttl";
|
||||
public static String MAX_RETRY_INTERVAL = "max-retry-interval";
|
||||
public static String MIN_LARGE_MESSAGE_SIZE = "min-large-message-size";
|
||||
public static String CALL_TIMEOUT = "call-timeout";
|
||||
public static String ROUTING_TYPE = "routing-type";
|
||||
|
||||
private String name = null;
|
||||
|
||||
private String queueName = null;
|
||||
|
@ -81,6 +115,110 @@ public final class BridgeConfiguration implements Serializable {
|
|||
public BridgeConfiguration() {
|
||||
}
|
||||
|
||||
public BridgeConfiguration(String name) {
|
||||
setName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a parameter based on its "key" {@code String}. Valid key names and corresponding {@code static}
|
||||
* {@code final} are:
|
||||
* <p><ul>
|
||||
* <li>name: {@link #NAME}
|
||||
* <li>queue-name: {@link #QUEUE_NAME}
|
||||
* <li>forwarding-address: {@link #FORWARDING_ADDRESS}
|
||||
* <li>filter-string: {@link #FILTER_STRING}
|
||||
* <li>static-connectors: {@link #STATIC_CONNECTORS}
|
||||
* <li>discovery-group-name: {@link #DISCOVERY_GROUP_NAME}
|
||||
* <li>ha: {@link #HA}
|
||||
* <li>transformer-configuration: {@link #TRANSFORMER_CONFIGURATION}
|
||||
* <li>retry-interval: {@link #RETRY_INTERVAL}
|
||||
* <li>RETRY-interval-multiplier: {@link #RETRY_INTERVAL_MULTIPLIER}
|
||||
* <li>initial-connect-attempts: {@link #INITIAL_CONNECT_ATTEMPTS}
|
||||
* <li>reconnect-attempts: {@link #RECONNECT_ATTEMPTS}
|
||||
* <li>reconnect-attempts-on-same-node: {@link #RECONNECT_ATTEMPTS_ON_SAME_NODE}
|
||||
* <li>use-duplicate-detection: {@link #USE_DUPLICATE_DETECTION}
|
||||
* <li>confirmation-window-size: {@link #CONFIRMATION_WINDOW_SIZE}
|
||||
* <li>producer-window-size: {@link #PRODUCER_WINDOW_SIZE}
|
||||
* <li>client-failure-check-period: {@link #CLIENT_FAILURE_CHECK_PERIOD}
|
||||
* <li>user: {@link #USER}
|
||||
* <li>password: {@link #PASSWORD}
|
||||
* <li>connection-ttl: {@link #CONNECTION_TTL}
|
||||
* <li>max-retry-interval: {@link #MAX_RETRY_INTERVAL}
|
||||
* <li>min-large-message-size: {@link #MIN_LARGE_MESSAGE_SIZE}
|
||||
* <li>call-timeout: {@link #CALL_TIMEOUT}
|
||||
* <li>routing-type: {@link #ROUTING_TYPE}
|
||||
* </ul><p>
|
||||
* The {@code String}-based values will be converted to the proper value types based on the underlying property. For
|
||||
* example, if you pass the value "TRUE" for the key "auto-created" the {@code String} "TRUE" will be converted to
|
||||
* the {@code Boolean} {@code true}.
|
||||
*
|
||||
* @param key the key to set to the value
|
||||
* @param value the value to set for the key
|
||||
* @return this {@code BridgeConfiguration}
|
||||
*/
|
||||
public BridgeConfiguration set(String key, String value) {
|
||||
if (key != null) {
|
||||
if (key.equals(NAME)) {
|
||||
setName(value);
|
||||
} else if (key.equals(QUEUE_NAME)) {
|
||||
setQueueName(value);
|
||||
} else if (key.equals(FORWARDING_ADDRESS)) {
|
||||
setForwardingAddress(value);
|
||||
} else if (key.equals(FILTER_STRING)) {
|
||||
setFilterString(value);
|
||||
} else if (key.equals(STATIC_CONNECTORS)) {
|
||||
// convert JSON array to string list
|
||||
List<String> stringList = JsonLoader.readArray(new StringReader(value)).stream()
|
||||
.map(v -> ((JsonString) v).getString())
|
||||
.collect(Collectors.toList());
|
||||
setStaticConnectors(stringList);
|
||||
} else if (key.equals(DISCOVERY_GROUP_NAME)) {
|
||||
setDiscoveryGroupName(value);
|
||||
} else if (key.equals(HA)) {
|
||||
setHA(Boolean.parseBoolean(value));
|
||||
} else if (key.equals(TRANSFORMER_CONFIGURATION)) {
|
||||
// create a transformer instance from a JSON string
|
||||
TransformerConfiguration transformerConfiguration = TransformerConfiguration.fromJSON(value);
|
||||
if (transformerConfiguration != null) {
|
||||
setTransformerConfiguration(transformerConfiguration);
|
||||
}
|
||||
} else if (key.equals(RETRY_INTERVAL)) {
|
||||
setRetryInterval(Long.parseLong(value));
|
||||
} else if (key.equals(RETRY_INTERVAL_MULTIPLIER)) {
|
||||
setRetryIntervalMultiplier(Double.parseDouble(value));
|
||||
} else if (key.equals(INITIAL_CONNECT_ATTEMPTS)) {
|
||||
setInitialConnectAttempts(Integer.parseInt(value));
|
||||
} else if (key.equals(RECONNECT_ATTEMPTS)) {
|
||||
setReconnectAttempts(Integer.parseInt(value));
|
||||
} else if (key.equals(RECONNECT_ATTEMPTS_ON_SAME_NODE)) {
|
||||
setReconnectAttemptsOnSameNode(Integer.parseInt(value));
|
||||
} else if (key.equals(USE_DUPLICATE_DETECTION)) {
|
||||
setUseDuplicateDetection(Boolean.parseBoolean(value));
|
||||
} else if (key.equals(CONFIRMATION_WINDOW_SIZE)) {
|
||||
setConfirmationWindowSize(Integer.parseInt(value));
|
||||
} else if (key.equals(PRODUCER_WINDOW_SIZE)) {
|
||||
setProducerWindowSize(Integer.parseInt(value));
|
||||
} else if (key.equals(CLIENT_FAILURE_CHECK_PERIOD)) {
|
||||
setClientFailureCheckPeriod(Long.parseLong(value));
|
||||
} else if (key.equals(USER)) {
|
||||
setUser(value);
|
||||
} else if (key.equals(PASSWORD)) {
|
||||
setPassword(value);
|
||||
} else if (key.equals(CONNECTION_TTL)) {
|
||||
setConnectionTTL(Long.parseLong(value));
|
||||
} else if (key.equals(MAX_RETRY_INTERVAL)) {
|
||||
setMaxRetryInterval(Long.parseLong(value));
|
||||
} else if (key.equals(MIN_LARGE_MESSAGE_SIZE)) {
|
||||
setMinLargeMessageSize(Integer.parseInt(value));
|
||||
} else if (key.equals(CALL_TIMEOUT)) {
|
||||
setCallTimeout(Long.parseLong(value));
|
||||
} else if (key.equals(ROUTING_TYPE)) {
|
||||
setRoutingType(ComponentConfigurationRoutingType.valueOf(value));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -360,6 +498,119 @@ public final class BridgeConfiguration implements Serializable {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a JSON-formatted {@code String} representation of this {@code BridgeConfiguration}. It is a
|
||||
* simple collection of key/value pairs. The keys used are referenced in {@link #set(String, String)}.
|
||||
*
|
||||
* @return a JSON-formatted {@code String} representation of this {@code BridgeConfiguration}
|
||||
*/
|
||||
public String toJSON() {
|
||||
JsonObjectBuilder builder = JsonLoader.createObjectBuilder();
|
||||
|
||||
// string fields which default to null (only serialize if value is not null)
|
||||
|
||||
if (getName() != null) {
|
||||
builder.add(NAME, getName());
|
||||
}
|
||||
if (getQueueName() != null) {
|
||||
builder.add(QUEUE_NAME, getQueueName());
|
||||
}
|
||||
if (getForwardingAddress() != null) {
|
||||
builder.add(FORWARDING_ADDRESS, getForwardingAddress());
|
||||
}
|
||||
if (getFilterString() != null) {
|
||||
builder.add(FILTER_STRING, getFilterString());
|
||||
}
|
||||
if (getDiscoveryGroupName() != null) {
|
||||
builder.add(DISCOVERY_GROUP_NAME, getDiscoveryGroupName());
|
||||
}
|
||||
|
||||
// string fields which default to non-null values (always serialize)
|
||||
|
||||
addNullable(builder, USER, getUser());
|
||||
addNullable(builder, PASSWORD, getPassword());
|
||||
|
||||
// primitive data type fields (always serialize)
|
||||
|
||||
builder.add(HA, isHA());
|
||||
builder.add(RETRY_INTERVAL, getRetryInterval());
|
||||
builder.add(RETRY_INTERVAL_MULTIPLIER, getRetryIntervalMultiplier());
|
||||
builder.add(INITIAL_CONNECT_ATTEMPTS, getInitialConnectAttempts());
|
||||
builder.add(RECONNECT_ATTEMPTS, getReconnectAttempts());
|
||||
builder.add(RECONNECT_ATTEMPTS_ON_SAME_NODE, getReconnectAttemptsOnSameNode());
|
||||
builder.add(USE_DUPLICATE_DETECTION, isUseDuplicateDetection());
|
||||
builder.add(CONFIRMATION_WINDOW_SIZE, getConfirmationWindowSize());
|
||||
builder.add(PRODUCER_WINDOW_SIZE, getProducerWindowSize());
|
||||
builder.add(CLIENT_FAILURE_CHECK_PERIOD, getClientFailureCheckPeriod());
|
||||
builder.add(CONNECTION_TTL, getConnectionTTL());
|
||||
builder.add(MAX_RETRY_INTERVAL, getMaxRetryInterval());
|
||||
builder.add(MIN_LARGE_MESSAGE_SIZE, getMinLargeMessageSize());
|
||||
builder.add(CALL_TIMEOUT, getCallTimeout());
|
||||
|
||||
// complex fields (only serialize if value is not null)
|
||||
|
||||
if (getRoutingType() != null) {
|
||||
builder.add(ROUTING_TYPE, getRoutingType().name());
|
||||
}
|
||||
|
||||
final List<String> staticConnectors = getStaticConnectors();
|
||||
if (staticConnectors != null) {
|
||||
JsonArrayBuilder arrayBuilder = JsonLoader.createArrayBuilder();
|
||||
staticConnectors.forEach(arrayBuilder::add);
|
||||
builder.add(STATIC_CONNECTORS, arrayBuilder);
|
||||
}
|
||||
|
||||
TransformerConfiguration tc = getTransformerConfiguration();
|
||||
if (tc != null) {
|
||||
JsonObjectBuilder tcBuilder = JsonLoader.createObjectBuilder().add(TransformerConfiguration.CLASS_NAME, tc.getClassName());
|
||||
if (tc.getProperties() != null && tc.getProperties().size() > 0) {
|
||||
JsonObjectBuilder propBuilder = JsonLoader.createObjectBuilder();
|
||||
tc.getProperties().forEach(propBuilder::add);
|
||||
tcBuilder.add(TransformerConfiguration.PROPERTIES, propBuilder);
|
||||
}
|
||||
builder.add(TRANSFORMER_CONFIGURATION, tcBuilder);
|
||||
}
|
||||
|
||||
return builder.build().toString();
|
||||
}
|
||||
|
||||
private static void addNullable(JsonObjectBuilder builder, String key, String value) {
|
||||
if (value == null) {
|
||||
builder.addNull(key);
|
||||
} else {
|
||||
builder.add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a {@code BridgeConfiguration} created from the JSON-formatted input {@code String}. The input
|
||||
* should be a simple object of key/value pairs. Valid keys are referenced in {@link #set(String, String)}.
|
||||
*
|
||||
* @param jsonString json string
|
||||
* @return the {@code BridgeConfiguration} created from the JSON-formatted input {@code String}
|
||||
*/
|
||||
public static BridgeConfiguration fromJSON(String jsonString) {
|
||||
JsonObject json = JsonLoader.readObject(new StringReader(jsonString));
|
||||
|
||||
// name is the only required value
|
||||
if (!json.containsKey(NAME)) {
|
||||
return null;
|
||||
}
|
||||
BridgeConfiguration result = new BridgeConfiguration(json.getString(NAME));
|
||||
|
||||
for (Map.Entry<String, JsonValue> entry : json.entrySet()) {
|
||||
if (entry.getValue().getValueType() == JsonValue.ValueType.STRING) {
|
||||
result.set(entry.getKey(), ((JsonString) entry.getValue()).getString());
|
||||
} else if (entry.getValue().getValueType() == JsonValue.ValueType.NULL) {
|
||||
result.set(entry.getKey(), null);
|
||||
} else {
|
||||
result.set(entry.getKey(), entry.getValue().toString());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
|
|
|
@ -3822,6 +3822,29 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createBridge(String bridgeConfigurationAsJson) throws Exception {
|
||||
if (AuditLogger.isEnabled()) {
|
||||
AuditLogger.createBridge(this.server, bridgeConfigurationAsJson);
|
||||
}
|
||||
checkStarted();
|
||||
|
||||
clearIO();
|
||||
|
||||
try {
|
||||
// when the BridgeConfiguration is passed through createBridge all of its defaults get set which we return to the caller
|
||||
BridgeConfiguration bridgeConfiguration = BridgeConfiguration.fromJSON(bridgeConfigurationAsJson);
|
||||
if (bridgeConfiguration == null) {
|
||||
throw ActiveMQMessageBundle.BUNDLE.failedToParseJson(bridgeConfigurationAsJson);
|
||||
}
|
||||
server.deployBridge(bridgeConfiguration);
|
||||
} catch (ActiveMQException e) {
|
||||
throw new IllegalStateException(e.getMessage());
|
||||
} finally {
|
||||
blockOnIO();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String listBrokerConnections() {
|
||||
if (AuditLogger.isEnabled()) {
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.core.config;
|
||||
|
||||
import org.apache.activemq.artemis.core.server.ComponentConfigurationRoutingType;
|
||||
import org.apache.activemq.artemis.utils.JsonLoader;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.json.JsonObject;
|
||||
import javax.json.JsonObjectBuilder;
|
||||
import javax.json.JsonValue;
|
||||
import javax.json.spi.JsonProvider;
|
||||
import java.io.StringReader;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
|
||||
public class BridgeConfigurationTest {
|
||||
|
||||
@Test
|
||||
public void testFromJSON() {
|
||||
String jsonString = createFullJsonObject().toString();
|
||||
|
||||
BridgeConfiguration bridgeConfiguration = BridgeConfiguration.fromJSON(jsonString);
|
||||
|
||||
Assert.assertNotNull(bridgeConfiguration);
|
||||
Assert.assertEquals("name", bridgeConfiguration.getName());
|
||||
Assert.assertEquals("queue-name", bridgeConfiguration.getQueueName());
|
||||
Assert.assertEquals("forwarding-address", bridgeConfiguration.getForwardingAddress());
|
||||
Assert.assertEquals("filter-string", bridgeConfiguration.getFilterString());
|
||||
Assert.assertArrayEquals(new String[]{"connector1", "connector2"},
|
||||
bridgeConfiguration.getStaticConnectors().toArray());
|
||||
Assert.assertEquals("dg", bridgeConfiguration.getDiscoveryGroupName());
|
||||
Assert.assertTrue(bridgeConfiguration.isHA());
|
||||
Assert.assertEquals("ClassName", bridgeConfiguration.getTransformerConfiguration().getClassName());
|
||||
Assert.assertThat(bridgeConfiguration.getTransformerConfiguration().getProperties().keySet(), containsInAnyOrder("prop1", "prop2"));
|
||||
Assert.assertEquals("val1", bridgeConfiguration.getTransformerConfiguration().getProperties().get("prop1"));
|
||||
Assert.assertEquals("val2", bridgeConfiguration.getTransformerConfiguration().getProperties().get("prop2"));
|
||||
Assert.assertEquals(1, bridgeConfiguration.getRetryInterval());
|
||||
Assert.assertEquals(2.0, bridgeConfiguration.getRetryIntervalMultiplier(), 0);
|
||||
Assert.assertEquals(3, bridgeConfiguration.getInitialConnectAttempts());
|
||||
Assert.assertEquals(4, bridgeConfiguration.getReconnectAttempts());
|
||||
Assert.assertEquals(5, bridgeConfiguration.getReconnectAttemptsOnSameNode());
|
||||
Assert.assertTrue(bridgeConfiguration.isUseDuplicateDetection());
|
||||
Assert.assertEquals(6, bridgeConfiguration.getConfirmationWindowSize());
|
||||
Assert.assertEquals(7, bridgeConfiguration.getProducerWindowSize());
|
||||
Assert.assertEquals(8, bridgeConfiguration.getClientFailureCheckPeriod());
|
||||
Assert.assertEquals("user", bridgeConfiguration.getUser());
|
||||
Assert.assertEquals("password", bridgeConfiguration.getPassword());
|
||||
Assert.assertEquals(9, bridgeConfiguration.getConnectionTTL());
|
||||
Assert.assertEquals(10, bridgeConfiguration.getMaxRetryInterval());
|
||||
Assert.assertEquals(11, bridgeConfiguration.getMinLargeMessageSize());
|
||||
Assert.assertEquals(12, bridgeConfiguration.getCallTimeout());
|
||||
Assert.assertEquals(ComponentConfigurationRoutingType.MULTICAST, bridgeConfiguration.getRoutingType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToJSON() {
|
||||
// create bc instance from a JSON object, all attributes are set
|
||||
JsonObject jsonObject = createFullJsonObject();
|
||||
BridgeConfiguration bridgeConfiguration = BridgeConfiguration.fromJSON(jsonObject.toString());
|
||||
Assert.assertNotNull(bridgeConfiguration);
|
||||
|
||||
// serialize it back to JSON
|
||||
String serializedBridgeConfiguration = bridgeConfiguration.toJSON();
|
||||
JsonObject serializedBridgeConfigurationJsonObject = JsonLoader.readObject(new StringReader(serializedBridgeConfiguration));
|
||||
|
||||
// verify that the original JSON object is identical to the one serialized via the toJSON() method
|
||||
Assert.assertEquals(jsonObject, serializedBridgeConfigurationJsonObject);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultsToJson() {
|
||||
// create and serialize BridgeConfiguration instance without modifying any fields
|
||||
BridgeConfiguration bridgeConfiguration = new BridgeConfiguration();
|
||||
String jsonString = bridgeConfiguration.toJSON();
|
||||
JsonObject jsonObject = JsonLoader.readObject(new StringReader(jsonString));
|
||||
|
||||
// the serialized JSON string should contain default values of primitive type fields
|
||||
Assert.assertEquals("2000", jsonObject.get(BridgeConfiguration.RETRY_INTERVAL).toString());
|
||||
Assert.assertEquals("1.0", jsonObject.get(BridgeConfiguration.RETRY_INTERVAL_MULTIPLIER).toString());
|
||||
Assert.assertEquals("-1", jsonObject.get(BridgeConfiguration.INITIAL_CONNECT_ATTEMPTS).toString());
|
||||
Assert.assertEquals("-1", jsonObject.get(BridgeConfiguration.RECONNECT_ATTEMPTS).toString());
|
||||
Assert.assertEquals("10", jsonObject.get(BridgeConfiguration.RECONNECT_ATTEMPTS_ON_SAME_NODE).toString());
|
||||
Assert.assertEquals("true", jsonObject.get(BridgeConfiguration.USE_DUPLICATE_DETECTION).toString());
|
||||
Assert.assertEquals("-1", jsonObject.get(BridgeConfiguration.CONFIRMATION_WINDOW_SIZE).toString());
|
||||
Assert.assertEquals("-1", jsonObject.get(BridgeConfiguration.PRODUCER_WINDOW_SIZE).toString());
|
||||
Assert.assertEquals("30000", jsonObject.get(BridgeConfiguration.CLIENT_FAILURE_CHECK_PERIOD).toString());
|
||||
Assert.assertEquals("2000", jsonObject.get(BridgeConfiguration.MAX_RETRY_INTERVAL).toString());
|
||||
Assert.assertEquals("102400", jsonObject.get(BridgeConfiguration.MIN_LARGE_MESSAGE_SIZE).toString());
|
||||
Assert.assertEquals("30000", jsonObject.get(BridgeConfiguration.CALL_TIMEOUT).toString());
|
||||
|
||||
// also should contain default non-null values of string fields
|
||||
Assert.assertEquals("\"ACTIVEMQ.CLUSTER.ADMIN.USER\"", jsonObject.get(BridgeConfiguration.USER).toString());
|
||||
Assert.assertEquals("\"CHANGE ME!!\"", jsonObject.get(BridgeConfiguration.PASSWORD).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultsFromJson() {
|
||||
// create BridgeConfiguration instance from empty JSON string
|
||||
final String jsonString = "{\"name\": \"name\"}"; // name field is required
|
||||
BridgeConfiguration deserializedConfiguration = BridgeConfiguration.fromJSON(jsonString);
|
||||
Assert.assertNotNull(deserializedConfiguration);
|
||||
|
||||
// the deserialized object should return the same default values as a newly instantiated object
|
||||
Assert.assertEquals(deserializedConfiguration, new BridgeConfiguration("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullableFieldsFromJson() {
|
||||
// set string fields which default value is not null to null
|
||||
JsonObjectBuilder builder = JsonLoader.createObjectBuilder();
|
||||
builder.add(BridgeConfiguration.NAME, "name"); // required field
|
||||
builder.addNull(BridgeConfiguration.USER);
|
||||
builder.addNull(BridgeConfiguration.PASSWORD);
|
||||
|
||||
BridgeConfiguration configuration = BridgeConfiguration.fromJSON(builder.build().toString());
|
||||
|
||||
// in deserialized object the fields should still remain null
|
||||
Assert.assertNotNull(configuration);
|
||||
Assert.assertEquals("name", configuration.getName());
|
||||
Assert.assertNull(configuration.getUser());
|
||||
Assert.assertNull(configuration.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullableFieldsToJson() {
|
||||
// set string fields which default value is not null to null
|
||||
BridgeConfiguration bridgeConfiguration = new BridgeConfiguration("name");
|
||||
bridgeConfiguration.setUser(null);
|
||||
bridgeConfiguration.setPassword(null);
|
||||
|
||||
String jsonString = bridgeConfiguration.toJSON();
|
||||
JsonObject jsonObject = JsonLoader.readObject(new StringReader(jsonString));
|
||||
|
||||
// after serialization the fields value should remain null
|
||||
Assert.assertEquals(JsonValue.ValueType.NULL, jsonObject.get(BridgeConfiguration.USER).getValueType());
|
||||
Assert.assertEquals(JsonValue.ValueType.NULL, jsonObject.get(BridgeConfiguration.PASSWORD).getValueType());
|
||||
}
|
||||
|
||||
private static JsonObject createFullJsonObject() {
|
||||
JsonObjectBuilder objectBuilder = JsonLoader.createObjectBuilder();
|
||||
|
||||
objectBuilder.add(BridgeConfiguration.NAME, "name");
|
||||
objectBuilder.add(BridgeConfiguration.QUEUE_NAME, "queue-name");
|
||||
objectBuilder.add(BridgeConfiguration.FORWARDING_ADDRESS, "forwarding-address");
|
||||
objectBuilder.add(BridgeConfiguration.FILTER_STRING, "filter-string");
|
||||
objectBuilder.add(BridgeConfiguration.STATIC_CONNECTORS,
|
||||
JsonProvider.provider().createArrayBuilder()
|
||||
.add("connector1")
|
||||
.add("connector2"));
|
||||
objectBuilder.add(BridgeConfiguration.DISCOVERY_GROUP_NAME, "dg");
|
||||
objectBuilder.add(BridgeConfiguration.HA, true);
|
||||
objectBuilder.add(BridgeConfiguration.TRANSFORMER_CONFIGURATION,
|
||||
JsonLoader.createObjectBuilder()
|
||||
.add("class-name", "ClassName")
|
||||
.add("properties",
|
||||
JsonLoader.createObjectBuilder()
|
||||
.add("prop1", "val1")
|
||||
.add("prop2", "val2")));
|
||||
objectBuilder.add(BridgeConfiguration.RETRY_INTERVAL, 1);
|
||||
objectBuilder.add(BridgeConfiguration.RETRY_INTERVAL_MULTIPLIER, 2.0);
|
||||
objectBuilder.add(BridgeConfiguration.INITIAL_CONNECT_ATTEMPTS, 3);
|
||||
objectBuilder.add(BridgeConfiguration.RECONNECT_ATTEMPTS, 4);
|
||||
objectBuilder.add(BridgeConfiguration.RECONNECT_ATTEMPTS_ON_SAME_NODE, 5);
|
||||
objectBuilder.add(BridgeConfiguration.USE_DUPLICATE_DETECTION, true);
|
||||
objectBuilder.add(BridgeConfiguration.CONFIRMATION_WINDOW_SIZE, 6);
|
||||
objectBuilder.add(BridgeConfiguration.PRODUCER_WINDOW_SIZE, 7);
|
||||
objectBuilder.add(BridgeConfiguration.CLIENT_FAILURE_CHECK_PERIOD, 8);
|
||||
objectBuilder.add(BridgeConfiguration.USER, "user");
|
||||
objectBuilder.add(BridgeConfiguration.PASSWORD, "password");
|
||||
objectBuilder.add(BridgeConfiguration.CONNECTION_TTL, 9);
|
||||
objectBuilder.add(BridgeConfiguration.MAX_RETRY_INTERVAL, 10);
|
||||
objectBuilder.add(BridgeConfiguration.MIN_LARGE_MESSAGE_SIZE, 11);
|
||||
objectBuilder.add(BridgeConfiguration.CALL_TIMEOUT, 12);
|
||||
objectBuilder.add(BridgeConfiguration.ROUTING_TYPE, "MULTICAST");
|
||||
|
||||
return objectBuilder.build();
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ import java.nio.ByteBuffer;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -60,6 +61,7 @@ import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
|
|||
import org.apache.activemq.artemis.api.jms.JMSFactoryType;
|
||||
import org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryImpl;
|
||||
import org.apache.activemq.artemis.core.client.impl.ClientSessionImpl;
|
||||
import org.apache.activemq.artemis.core.config.BridgeConfiguration;
|
||||
import org.apache.activemq.artemis.core.config.ClusterConnectionConfiguration;
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.config.impl.SecurityConfiguration;
|
||||
|
@ -1878,6 +1880,96 @@ public class ActiveMQServerControlTest extends ManagementTestBase {
|
|||
locator.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndDestroyBridgeFromJson() throws Exception {
|
||||
String name = RandomUtil.randomString();
|
||||
String sourceAddress = RandomUtil.randomString();
|
||||
String sourceQueue = RandomUtil.randomString();
|
||||
String targetAddress = RandomUtil.randomString();
|
||||
String targetQueue = RandomUtil.randomString();
|
||||
|
||||
ActiveMQServerControl serverControl = createManagementControl();
|
||||
|
||||
checkNoResource(ObjectNameBuilder.DEFAULT.getBridgeObjectName(name));
|
||||
assertEquals(0, serverControl.getBridgeNames().length);
|
||||
|
||||
ServerLocator locator = createInVMNonHALocator();
|
||||
ClientSessionFactory csf = createSessionFactory(locator);
|
||||
ClientSession session = csf.createSession();
|
||||
|
||||
if (legacyCreateQueue) {
|
||||
session.createQueue(sourceAddress, RoutingType.ANYCAST, sourceQueue);
|
||||
session.createQueue(targetAddress, RoutingType.ANYCAST, targetQueue);
|
||||
} else {
|
||||
session.createQueue(new QueueConfiguration(sourceQueue).setAddress(sourceAddress).setRoutingType(RoutingType.ANYCAST).setDurable(false));
|
||||
session.createQueue(new QueueConfiguration(targetQueue).setAddress(targetAddress).setRoutingType(RoutingType.ANYCAST).setDurable(false));
|
||||
}
|
||||
|
||||
BridgeConfiguration bridgeConfiguration = new BridgeConfiguration(name)
|
||||
.setQueueName(sourceQueue)
|
||||
.setForwardingAddress(targetAddress)
|
||||
.setUseDuplicateDetection(false)
|
||||
.setConfirmationWindowSize(1)
|
||||
.setProducerWindowSize(-1)
|
||||
.setStaticConnectors(Collections.singletonList(connectorConfig.getName()))
|
||||
.setHA(false)
|
||||
.setUser(null)
|
||||
.setPassword(null);
|
||||
serverControl.createBridge(bridgeConfiguration.toJSON());
|
||||
|
||||
checkResource(ObjectNameBuilder.DEFAULT.getBridgeObjectName(name));
|
||||
String[] bridgeNames = serverControl.getBridgeNames();
|
||||
assertEquals(1, bridgeNames.length);
|
||||
assertEquals(name, bridgeNames[0]);
|
||||
|
||||
BridgeControl bridgeControl = ManagementControlHelper.createBridgeControl(name, mbeanServer);
|
||||
assertEquals(name, bridgeControl.getName());
|
||||
assertTrue(bridgeControl.isStarted());
|
||||
|
||||
// check that a message sent to the sourceAddress is put in the tagetQueue
|
||||
ClientProducer producer = session.createProducer(sourceAddress);
|
||||
ClientMessage message = session.createMessage(false);
|
||||
String text = RandomUtil.randomString();
|
||||
message.putStringProperty("prop", text);
|
||||
producer.send(message);
|
||||
|
||||
session.start();
|
||||
|
||||
ClientConsumer targetConsumer = session.createConsumer(targetQueue);
|
||||
message = targetConsumer.receive(5000);
|
||||
assertNotNull(message);
|
||||
assertEquals(text, message.getStringProperty("prop"));
|
||||
|
||||
ClientConsumer sourceConsumer = session.createConsumer(sourceQueue);
|
||||
assertNull(sourceConsumer.receiveImmediate());
|
||||
|
||||
serverControl.destroyBridge(name);
|
||||
|
||||
checkNoResource(ObjectNameBuilder.DEFAULT.getBridgeObjectName(name));
|
||||
assertEquals(0, serverControl.getBridgeNames().length);
|
||||
|
||||
// check that a message is no longer diverted
|
||||
message = session.createMessage(false);
|
||||
String text2 = RandomUtil.randomString();
|
||||
message.putStringProperty("prop", text2);
|
||||
producer.send(message);
|
||||
|
||||
assertNull(targetConsumer.receiveImmediate());
|
||||
message = sourceConsumer.receive(5000);
|
||||
assertNotNull(message);
|
||||
assertEquals(text2, message.getStringProperty("prop"));
|
||||
|
||||
sourceConsumer.close();
|
||||
targetConsumer.close();
|
||||
|
||||
session.deleteQueue(sourceQueue);
|
||||
session.deleteQueue(targetQueue);
|
||||
|
||||
session.close();
|
||||
|
||||
locator.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListPreparedTransactionDetails() throws Exception {
|
||||
SimpleString atestq = new SimpleString("BasicXaTestq");
|
||||
|
|
|
@ -1556,6 +1556,11 @@ public class ActiveMQServerControlUsingCoreTest extends ActiveMQServerControlTes
|
|||
proxy.invokeOperation("createBridge", name, queueName, forwardingAddress, filterString, transformerClassName, retryInterval, retryIntervalMultiplier, initialConnectAttempts, reconnectAttempts, useDuplicateDetection, confirmationWindowSize, clientFailureCheckPeriod, connectorNames, useDiscovery, ha, user, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createBridge(String bridgeConfiguration) throws Exception {
|
||||
proxy.invokeOperation("createBridge", bridgeConfiguration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String listProducersInfoAsJSON() throws Exception {
|
||||
return (String) proxy.invokeOperation("listProducersInfoAsJSON");
|
||||
|
|
Loading…
Reference in New Issue