Repository: activemq-artemis Updated Branches: refs/heads/2.6.x f4734868a -> 0608ff045
Revert "ARTEMIS-2095 - Typed Properties ThreadSafety" This reverts commit 2aa7844d58b21f3772c08b41344888ff8380431c. This commit is wrong, i will re-apply Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/0608ff04 Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/0608ff04 Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/0608ff04 Branch: refs/heads/2.6.x Commit: 0608ff04597d16f1ad467d22f46b7422b7137ab3 Parents: f473486 Author: Clebert Suconic <[email protected]> Authored: Thu Sep 27 18:18:20 2018 -0400 Committer: Clebert Suconic <[email protected]> Committed: Thu Sep 27 18:18:20 2018 -0400 ---------------------------------------------------------------------- .../utils/collections/TypedProperties.java | 138 +++++++--------- .../utils/TypedPropertiesConcurrencyTest.java | 162 ------------------- .../artemis/jms/client/ActiveMQJMSProducer.java | 19 ++- .../artemis/jms/client/ActiveMQMapMessage.java | 11 +- .../amqp/converter/AmqpCoreConverter.java | 24 ++- .../amqp/converter/jms/ServerJMSMapMessage.java | 11 +- .../management/impl/ManagementServiceImpl.java | 4 +- 7 files changed, 104 insertions(+), 265 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/0608ff04/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/TypedProperties.java ---------------------------------------------------------------------- diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/TypedProperties.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/TypedProperties.java index 4cf4805..aa2d551 100644 --- a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/TypedProperties.java +++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/TypedProperties.java @@ -16,17 +16,15 @@ */ package org.apache.activemq.artemis.utils.collections; -import io.netty.buffer.ByteBuf; import java.nio.ByteBuffer; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.Consumer; + +import io.netty.buffer.ByteBuf; import org.apache.activemq.artemis.api.core.ActiveMQPropertyConversionException; import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.logs.ActiveMQUtilBundle; @@ -59,7 +57,7 @@ public class TypedProperties { private Map<SimpleString, PropertyValue> properties; - private int size; + private volatile int size; private boolean internalProperties; @@ -69,11 +67,11 @@ public class TypedProperties { /** * Return the number of properties * */ - public synchronized int size() { - return properties == null ? 0 : properties.size(); + public int size() { + return properties.size(); } - public synchronized int getMemoryOffset() { + public int getMemoryOffset() { // The estimate is basically the encode size + 2 object references for each entry in the map // Note we don't include the attributes or anything else since they already included in the memory estimate // of the ServerMessage @@ -88,60 +86,75 @@ public class TypedProperties { } } - public synchronized boolean hasInternalProperties() { + public boolean hasInternalProperties() { return internalProperties; } public void putBooleanProperty(final SimpleString key, final boolean value) { + checkCreateProperties(); doPutValue(key, BooleanValue.of(value)); } public void putByteProperty(final SimpleString key, final byte value) { + checkCreateProperties(); doPutValue(key, ByteValue.valueOf(value)); } public void putBytesProperty(final SimpleString key, final byte[] value) { + checkCreateProperties(); doPutValue(key, value == null ? NullValue.INSTANCE : new BytesValue(value)); } public void putShortProperty(final SimpleString key, final short value) { + checkCreateProperties(); doPutValue(key, new ShortValue(value)); } public void putIntProperty(final SimpleString key, final int value) { + checkCreateProperties(); doPutValue(key, new IntValue(value)); } public void putLongProperty(final SimpleString key, final long value) { + checkCreateProperties(); doPutValue(key, new LongValue(value)); } public void putFloatProperty(final SimpleString key, final float value) { + checkCreateProperties(); doPutValue(key, new FloatValue(value)); } public void putDoubleProperty(final SimpleString key, final double value) { + checkCreateProperties(); doPutValue(key, new DoubleValue(value)); } public void putSimpleStringProperty(final SimpleString key, final SimpleString value) { + checkCreateProperties(); doPutValue(key, value == null ? NullValue.INSTANCE : new StringValue(value)); } public void putNullValue(final SimpleString key) { + checkCreateProperties(); doPutValue(key, NullValue.INSTANCE); } public void putCharProperty(final SimpleString key, final char value) { + checkCreateProperties(); doPutValue(key, new CharValue(value)); } public void putTypedProperties(final TypedProperties otherProps) { - if (otherProps == null || otherProps == this || otherProps.properties == null) { + if (otherProps == null || otherProps.properties == null) { return; } - otherProps.forEachInternal(this::doPutValue); + checkCreateProperties(); + Set<Entry<SimpleString, PropertyValue>> otherEntries = otherProps.properties.entrySet(); + for (Entry<SimpleString, PropertyValue> otherEntry : otherEntries) { + doPutValue(otherEntry.getKey(), otherEntry.getValue()); + } } public Object getProperty(final SimpleString key) { @@ -302,46 +315,29 @@ public class TypedProperties { return doRemoveProperty(key); } - public synchronized boolean containsProperty(final SimpleString key) { - if (properties == null) { + public boolean containsProperty(final SimpleString key) { + if (size == 0) { return false; } else { return properties.containsKey(key); } } - public synchronized Set<SimpleString> getPropertyNames() { - if (properties == null) { + + public Set<SimpleString> getPropertyNames() { + if (size == 0) { return Collections.emptySet(); } else { - return new HashSet<>(properties.keySet()); - } - } - - public synchronized void forEachKey(Consumer<SimpleString> action) { - if (properties != null) { - properties.keySet().forEach(action::accept); - } - } - - public synchronized void forEach(BiConsumer<SimpleString, Object> action) { - if (properties != null) { - properties.forEach((k, v) -> action.accept(k, v.getValue())); - } - } - - private synchronized void forEachInternal(BiConsumer<SimpleString, PropertyValue> action) { - if (properties != null) { - properties.forEach(action::accept); + return properties.keySet(); } } public synchronized void decode(final ByteBuf buffer, final TypedPropertiesDecoderPools keyValuePools) { byte b = buffer.readByte(); + if (b == DataConstants.NULL) { properties = null; - size = 0; } else { int numHeaders = buffer.readInt(); @@ -420,13 +416,12 @@ public class TypedProperties { } } - public void decode(final ByteBuf buffer) { + public synchronized void decode(final ByteBuf buffer) { decode(buffer, null); } - public synchronized void encode(final ByteBuf buffer) { - if (properties == null || size == 0) { + if (properties == null) { buffer.writeByte(DataConstants.NULL); } else { buffer.writeByte(DataConstants.NOT_NULL); @@ -443,26 +438,26 @@ public class TypedProperties { } } - public synchronized int getEncodeSize() { - if (properties == null || size == 0) { + public int getEncodeSize() { + if (properties == null) { return DataConstants.SIZE_BYTE; } else { return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + size; } } - public synchronized void clear() { + public void clear() { if (properties != null) { properties.clear(); } - size = 0; } @Override - public synchronized String toString() { + public String toString() { StringBuilder sb = new StringBuilder("TypedProperties["); if (properties != null) { + Iterator<Entry<SimpleString, PropertyValue>> iter = properties.entrySet().iterator(); while (iter.hasNext()) { @@ -510,15 +505,17 @@ public class TypedProperties { // Private ------------------------------------------------------------------------------------ + private void checkCreateProperties() { + if (properties == null) { + properties = new HashMap<>(); + } + } + private synchronized void doPutValue(final SimpleString key, final PropertyValue value) { if (key.startsWith(AMQ_PROPNAME)) { internalProperties = true; } - if (properties == null) { - properties = new HashMap<>(); - } - PropertyValue oldValue = properties.put(key, value); if (oldValue != null) { size += value.encodeSize() - oldValue.encodeSize(); @@ -533,20 +530,23 @@ public class TypedProperties { } PropertyValue val = properties.remove(key); + if (val == null) { return null; } else { size -= SimpleString.sizeofString(key) + val.encodeSize(); + return val.getValue(); } } private synchronized Object doGetProperty(final Object key) { - if (properties == null) { + if (size == 0) { return null; } PropertyValue val = properties.get(key); + if (val == null) { return null; } else { @@ -1003,41 +1003,21 @@ public class TypedProperties { } } - public synchronized boolean isEmpty() { - if (properties == null) { - return true; - } else { - return properties.isEmpty(); - } - } - - public synchronized Set<String> getMapNames() { - if (properties == null) { - return Collections.emptySet(); - } else { - Set<String> names = new HashSet<>(properties.size()); - for (SimpleString name : properties.keySet()) { - names.add(name.toString()); - } - return names; - } + public boolean isEmpty() { + return properties.isEmpty(); } - public synchronized Map<String, Object> getMap() { - if (properties == null) { - return Collections.emptyMap(); - } else { - Map<String, Object> m = new HashMap<>(properties.size()); - for (Entry<SimpleString, PropertyValue> entry : properties.entrySet()) { - Object val = entry.getValue().getValue(); - if (val instanceof SimpleString) { - m.put(entry.getKey().toString(), ((SimpleString) val).toString()); - } else { - m.put(entry.getKey().toString(), val); - } + public Map<String, Object> getMap() { + Map<String, Object> m = new HashMap<>(); + for (Entry<SimpleString, PropertyValue> entry : properties.entrySet()) { + Object val = entry.getValue().getValue(); + if (val instanceof SimpleString) { + m.put(entry.getKey().toString(), ((SimpleString) val).toString()); + } else { + m.put(entry.getKey().toString(), val); } - return m; } + return m; } /** http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/0608ff04/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/TypedPropertiesConcurrencyTest.java ---------------------------------------------------------------------- diff --git a/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/TypedPropertiesConcurrencyTest.java b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/TypedPropertiesConcurrencyTest.java deleted file mode 100644 index 9e9e86a..0000000 --- a/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/TypedPropertiesConcurrencyTest.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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.utils; - - -import java.util.ConcurrentModificationException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.activemq.artemis.api.core.SimpleString; -import org.apache.activemq.artemis.utils.collections.TypedProperties; -import org.junit.Assert; -import static org.junit.Assert.assertEquals; -import org.junit.Test; - -public class TypedPropertiesConcurrencyTest { - - // Constructors -------------------------------------------------- - - // Public -------------------------------------------------------- - - - private SimpleString key = SimpleString.toSimpleString("key"); - - @Test - public void testClearAndToString() throws Exception { - TypedProperties props = new TypedProperties(); - - ExecutorService executorService = Executors.newFixedThreadPool(1000); - - AtomicBoolean hasError = new AtomicBoolean(); - CountDownLatch countDownLatch = new CountDownLatch(1); - for (int i = 0; i < 10000; i++) { - int g = i; - executorService.submit(() -> { - try { - countDownLatch.await(); - for (int h = 0; h < 100; h++) { - props.putSimpleStringProperty(SimpleString.toSimpleString("S" + h), SimpleString.toSimpleString("hello")); - } - props.clear(); - } catch (ConcurrentModificationException t) { - hasError.set(true); - t.printStackTrace(); - } catch (InterruptedException e) { - } - }); - } - for (int i = 0; i < 10; i++) { - executorService.submit( () -> { - try { - countDownLatch.await(); - for (int k = 0; k < 1000; k++) { - props.toString(); - } - } catch (ConcurrentModificationException t) { - hasError.set(true); - t.printStackTrace(); - } catch (InterruptedException e) { - } - - }); - } - - countDownLatch.countDown(); - Thread.sleep(1000); - executorService.shutdown(); - executorService.awaitTermination(10, TimeUnit.SECONDS); - executorService.shutdown(); - Assert.assertFalse(hasError.get()); - } - - - @Test - public void testGetPropertyNamesClearAndToString() throws Exception { - TypedProperties props = new TypedProperties(); - - ExecutorService executorService = Executors.newFixedThreadPool(1000); - - AtomicBoolean hasError = new AtomicBoolean(); - CountDownLatch countDownLatch = new CountDownLatch(1); - for (int i = 0; i < 10000; i++) { - int g = i; - executorService.submit(() -> { - try { - countDownLatch.await(); - for (int h = 0; h < 100; h++) { - props.putSimpleStringProperty(SimpleString.toSimpleString("S" + h), SimpleString.toSimpleString("hello")); - } - props.getPropertyNames().clear(); - } catch (UnsupportedOperationException uoe) { - //Catch this as this would be acceptable, as the set is meant to be like an enumeration so a user should not modify and should expect an implementation to protect itself.. - } catch (ConcurrentModificationException t) { - hasError.set(true); - t.printStackTrace(); - } catch (InterruptedException e) { - } - }); - } - for (int i = 0; i < 10; i++) { - executorService.submit( () -> { - try { - countDownLatch.await(); - for (int k = 0; k < 1000; k++) { - props.toString(); - } - } catch (ConcurrentModificationException t) { - hasError.set(true); - t.printStackTrace(); - } catch (InterruptedException e) { - } - - }); - } - - countDownLatch.countDown(); - Thread.sleep(1000); - executorService.shutdown(); - executorService.awaitTermination(10, TimeUnit.SECONDS); - executorService.shutdown(); - Assert.assertFalse(hasError.get()); - } - - - @Test - public void testEncodedSizeAfterClearIsSameAsNewTypedProperties() throws Exception { - TypedProperties props = new TypedProperties(); - props.putSimpleStringProperty(SimpleString.toSimpleString("helllllloooooo"), SimpleString.toSimpleString("raaaaaaaaaaaaaaaaaaaaaaaa")); - - props.clear(); - - assertEquals(new TypedProperties().getEncodeSize(), props.getEncodeSize()); - - } - - @Test - public void testMemoryOffsetAfterClearIsSameAsNewTypedProperties() throws Exception { - TypedProperties props = new TypedProperties(); - props.putSimpleStringProperty(SimpleString.toSimpleString("helllllloooooo"), SimpleString.toSimpleString("raaaaaaaaaaaaaaaaaaaaaaaa")); - - props.clear(); - - assertEquals(new TypedProperties().getMemoryOffset(), props.getMemoryOffset()); - - } -} http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/0608ff04/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQJMSProducer.java ---------------------------------------------------------------------- diff --git a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQJMSProducer.java b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQJMSProducer.java index e97a3c2..965eefd 100644 --- a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQJMSProducer.java +++ b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQJMSProducer.java @@ -31,6 +31,7 @@ import javax.jms.TextMessage; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -109,13 +110,9 @@ public final class ActiveMQJMSProducer implements JMSProducer { * @throws JMSException */ private void setProperties(Message message) throws JMSException { - properties.forEach((k, v) -> { - try { - message.setObjectProperty(k.toString(), v); - } catch (JMSException e) { - throw JmsExceptionUtils.convertToRuntimeException(e); - } - }); + for (SimpleString name : properties.getPropertyNames()) { + message.setObjectProperty(name.toString(), properties.getProperty(name)); + } } @Override @@ -514,7 +511,13 @@ public final class ActiveMQJMSProducer implements JMSProducer { @Override public Set<String> getPropertyNames() { try { - return properties.getMapNames(); + Set<SimpleString> simplePropNames = properties.getPropertyNames(); + Set<String> propNames = new HashSet<>(simplePropNames.size()); + + for (SimpleString str : simplePropNames) { + propNames.add(str.toString()); + } + return propNames; } catch (ActiveMQPropertyConversionException ce) { throw new MessageFormatRuntimeException(ce.getMessage()); } catch (RuntimeException e) { http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/0608ff04/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQMapMessage.java ---------------------------------------------------------------------- diff --git a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQMapMessage.java b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQMapMessage.java index e0249bf..557b0b8 100644 --- a/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQMapMessage.java +++ b/artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQMapMessage.java @@ -21,6 +21,8 @@ import javax.jms.MapMessage; import javax.jms.MessageFormatException; import java.util.Collections; import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; import org.apache.activemq.artemis.api.core.ActiveMQException; import org.apache.activemq.artemis.api.core.ActiveMQPropertyConversionException; @@ -299,7 +301,14 @@ public class ActiveMQMapMessage extends ActiveMQMessage implements MapMessage { @Override public Enumeration getMapNames() throws JMSException { - return Collections.enumeration(map.getMapNames()); + Set<SimpleString> simplePropNames = map.getPropertyNames(); + Set<String> propNames = new HashSet<>(simplePropNames.size()); + + for (SimpleString str : simplePropNames) { + propNames.add(str.toString()); + } + + return Collections.enumeration(propNames); } @Override http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/0608ff04/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/AmqpCoreConverter.java ---------------------------------------------------------------------- diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/AmqpCoreConverter.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/AmqpCoreConverter.java index 4948e9d..d070579 100644 --- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/AmqpCoreConverter.java +++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/AmqpCoreConverter.java @@ -51,6 +51,7 @@ import javax.jms.DeliveryMode; import javax.jms.JMSException; import org.apache.activemq.artemis.api.core.ICoreMessage; +import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.core.message.impl.CoreMessageObjectPools; import org.apache.activemq.artemis.protocol.amqp.broker.AMQPMessage; import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerDestination; @@ -175,13 +176,22 @@ public class AmqpCoreConverter { throw new RuntimeException("Unexpected body type: " + body.getClass()); } - processExtraProperties(result, message.getExtraProperties()); + TypedProperties properties = message.getExtraProperties(); + if (properties != null) { + for (SimpleString str : properties.getPropertyNames()) { + if (str.equals(AMQPMessage.ADDRESS_PROPERTY)) { + continue; + } + result.getInnerMessage().putBytesProperty(str, properties.getBytesProperty(str)); + } + } populateMessage(result, message.getProtonMessage()); result.getInnerMessage().setReplyTo(message.getReplyTo()); result.getInnerMessage().setDurable(message.isDurable()); result.getInnerMessage().setPriority(message.getPriority()); result.getInnerMessage().setAddress(message.getAddressSimpleString()); + result.encode(); return result != null ? result.getInnerMessage() : null; @@ -316,18 +326,6 @@ public class AmqpCoreConverter { return jms; } - private static ServerJMSMessage processExtraProperties(ServerJMSMessage jms, TypedProperties properties) { - if (properties != null) { - properties.forEach((k, v) -> { - if (!k.equals(AMQPMessage.ADDRESS_PROPERTY)) { - jms.getInnerMessage().putObjectProperty(k, v); - } - }); - } - - return jms; - } - private static void setProperty(javax.jms.Message msg, String key, Object value) throws JMSException { if (value instanceof UnsignedLong) { long v = ((UnsignedLong) value).longValue(); http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/0608ff04/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/jms/ServerJMSMapMessage.java ---------------------------------------------------------------------- diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/jms/ServerJMSMapMessage.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/jms/ServerJMSMapMessage.java index 9ee86af..588b10e 100644 --- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/jms/ServerJMSMapMessage.java +++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/jms/ServerJMSMapMessage.java @@ -21,6 +21,8 @@ import javax.jms.MapMessage; import javax.jms.MessageFormatException; import java.util.Collections; import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; import org.apache.activemq.artemis.api.core.ActiveMQPropertyConversionException; import org.apache.activemq.artemis.api.core.ICoreMessage; @@ -249,7 +251,14 @@ public final class ServerJMSMapMessage extends ServerJMSMessage implements MapMe @Override public Enumeration getMapNames() throws JMSException { - return Collections.enumeration(map.getMapNames()); + Set<SimpleString> simplePropNames = map.getPropertyNames(); + Set<String> propNames = new HashSet<>(simplePropNames.size()); + + for (SimpleString str : simplePropNames) { + propNames.add(str.toString()); + } + + return Collections.enumeration(propNames); } @Override http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/0608ff04/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/impl/ManagementServiceImpl.java ---------------------------------------------------------------------- diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/impl/ManagementServiceImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/impl/ManagementServiceImpl.java index ecb8d55..ad888d0 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/impl/ManagementServiceImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/management/impl/ManagementServiceImpl.java @@ -679,7 +679,9 @@ public class ManagementServiceImpl implements ManagementService { if (notification.getProperties() != null) { TypedProperties props = notification.getProperties(); - props.forEach(notificationMessage::putObjectProperty); + for (SimpleString name : notification.getProperties().getPropertyNames()) { + notificationMessage.putObjectProperty(name, props.getProperty(name)); + } } notificationMessage.putStringProperty(ManagementHelper.HDR_NOTIFICATION_TYPE, new SimpleString(notification.getType().toString()));
