This closes #2568
This commit is contained in:
commit
7fceaeb6c0
|
@ -266,6 +266,15 @@ public interface Message {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default Object getCorrelationID() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default Message setCorrelationID(Object correlationID) {
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
SimpleString getReplyTo();
|
SimpleString getReplyTo();
|
||||||
|
|
||||||
Message setReplyTo(SimpleString address);
|
Message setReplyTo(SimpleString address);
|
||||||
|
|
|
@ -297,6 +297,17 @@ public class CoreMessage extends RefCountMessage implements ICoreMessage {
|
||||||
return this.putIntProperty(Message.HDR_GROUP_SEQUENCE, sequence);
|
return this.putIntProperty(Message.HDR_GROUP_SEQUENCE, sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getCorrelationID() {
|
||||||
|
return getObjectProperty(MessageUtil.CORRELATIONID_HEADER_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message setCorrelationID(final Object correlationID) {
|
||||||
|
putObjectProperty(MessageUtil.CORRELATIONID_HEADER_NAME, correlationID);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param sendBuffer
|
* @param sendBuffer
|
||||||
* @param deliveryCount Some protocols (AMQP) will have this as part of the message. ignored on core
|
* @param deliveryCount Some protocols (AMQP) will have this as part of the message. ignored on core
|
||||||
|
|
|
@ -1147,6 +1147,21 @@ public class AMQPMessage extends RefCountMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getCorrelationID() {
|
||||||
|
return properties != null ? properties.getCorrelationId() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public org.apache.activemq.artemis.api.core.Message setCorrelationID(final Object correlationID) {
|
||||||
|
if (properties == null) {
|
||||||
|
properties = new Properties();
|
||||||
|
}
|
||||||
|
|
||||||
|
properties.setCorrelationId(correlationID);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long getScheduledDeliveryTime() {
|
public Long getScheduledDeliveryTime() {
|
||||||
if (scheduledTime < 0) {
|
if (scheduledTime < 0) {
|
||||||
|
|
|
@ -325,8 +325,13 @@ public class AmqpCoreConverter {
|
||||||
if (properties.getReplyTo() != null) {
|
if (properties.getReplyTo() != null) {
|
||||||
jms.setJMSReplyTo(new ServerDestination(properties.getReplyTo()));
|
jms.setJMSReplyTo(new ServerDestination(properties.getReplyTo()));
|
||||||
}
|
}
|
||||||
if (properties.getCorrelationId() != null) {
|
Object correlationID = properties.getCorrelationId();
|
||||||
jms.setJMSCorrelationID(AMQPMessageIdHelper.INSTANCE.toCorrelationIdString(properties.getCorrelationId()));
|
if (correlationID != null) {
|
||||||
|
try {
|
||||||
|
jms.getInnerMessage().setCorrelationID(AMQPMessageIdHelper.INSTANCE.toCorrelationIdString(correlationID));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
jms.getInnerMessage().setCorrelationID(String.valueOf(correlationID));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (properties.getContentType() != null) {
|
if (properties.getContentType() != null) {
|
||||||
jms.setStringProperty(JMS_AMQP_CONTENT_TYPE, properties.getContentType().toString());
|
jms.setStringProperty(JMS_AMQP_CONTENT_TYPE, properties.getContentType().toString());
|
||||||
|
|
|
@ -72,6 +72,7 @@ import javax.jms.Topic;
|
||||||
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
|
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
|
||||||
import org.apache.activemq.artemis.api.core.ICoreMessage;
|
import org.apache.activemq.artemis.api.core.ICoreMessage;
|
||||||
import org.apache.activemq.artemis.api.core.Message;
|
import org.apache.activemq.artemis.api.core.Message;
|
||||||
|
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||||
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPMessage;
|
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPMessage;
|
||||||
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSBytesMessage;
|
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSBytesMessage;
|
||||||
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSMapMessage;
|
import org.apache.activemq.artemis.protocol.amqp.converter.jms.ServerJMSMapMessage;
|
||||||
|
@ -177,14 +178,19 @@ public class CoreAmqpConverter {
|
||||||
properties.setReplyTo(toAddress(replyTo));
|
properties.setReplyTo(toAddress(replyTo));
|
||||||
maMap.put(JMS_REPLY_TO_TYPE_MSG_ANNOTATION, destinationType(replyTo));
|
maMap.put(JMS_REPLY_TO_TYPE_MSG_ANNOTATION, destinationType(replyTo));
|
||||||
}
|
}
|
||||||
String correlationId = message.getJMSCorrelationID();
|
|
||||||
if (correlationId != null) {
|
Object correlationID = message.getInnerMessage().getCorrelationID();
|
||||||
|
if (correlationID instanceof String || correlationID instanceof SimpleString) {
|
||||||
|
String c = correlationID instanceof String ? ((String) correlationID) : ((SimpleString) correlationID).toString();
|
||||||
try {
|
try {
|
||||||
properties.setCorrelationId(AMQPMessageIdHelper.INSTANCE.toIdObject(correlationId));
|
properties.setCorrelationId(AMQPMessageIdHelper.INSTANCE.toIdObject(c));
|
||||||
} catch (ActiveMQAMQPIllegalStateException e) {
|
} catch (ActiveMQAMQPIllegalStateException e) {
|
||||||
properties.setCorrelationId(correlationId);
|
properties.setCorrelationId(correlationID);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
properties.setCorrelationId(correlationID);
|
||||||
}
|
}
|
||||||
|
|
||||||
long expiration = message.getJMSExpiration();
|
long expiration = message.getJMSExpiration();
|
||||||
if (expiration != 0) {
|
if (expiration != 0) {
|
||||||
long ttl = expiration - System.currentTimeMillis();
|
long ttl = expiration - System.currentTimeMillis();
|
||||||
|
|
|
@ -24,7 +24,6 @@ import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
|
||||||
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
|
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
|
||||||
import org.apache.activemq.artemis.api.core.ActiveMQException;
|
|
||||||
import org.apache.activemq.artemis.api.core.ICoreMessage;
|
import org.apache.activemq.artemis.api.core.ICoreMessage;
|
||||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||||
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
|
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
|
||||||
|
@ -118,21 +117,29 @@ public class ServerJMSMessage implements Message {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void setJMSCorrelationIDAsBytes(byte[] correlationID) throws JMSException {
|
public final void setJMSCorrelationIDAsBytes(byte[] correlationID) throws JMSException {
|
||||||
try {
|
if (correlationID == null || correlationID.length == 0) {
|
||||||
MessageUtil.setJMSCorrelationIDAsBytes(message, correlationID);
|
throw new JMSException("Please specify a non-zero length byte[]");
|
||||||
} catch (ActiveMQException e) {
|
|
||||||
throw new JMSException(e.getMessage());
|
|
||||||
}
|
}
|
||||||
|
message.setCorrelationID(correlationID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final String getJMSCorrelationID() throws JMSException {
|
public final String getJMSCorrelationID() throws JMSException {
|
||||||
return MessageUtil.getJMSCorrelationID(message);
|
|
||||||
|
Object correlationID = message.getCorrelationID();
|
||||||
|
if (correlationID instanceof String) {
|
||||||
|
|
||||||
|
return ((String) correlationID);
|
||||||
|
} else if (correlationID != null) {
|
||||||
|
return String.valueOf(correlationID);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void setJMSCorrelationID(String correlationID) throws JMSException {
|
public final void setJMSCorrelationID(String correlationID) throws JMSException {
|
||||||
MessageUtil.setJMSCorrelationID(message, correlationID);
|
message.setCorrelationID(correlationID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.activemq.artemis.core.server.management.impl;
|
package org.apache.activemq.artemis.core.server.management.impl;
|
||||||
|
|
||||||
|
import static org.apache.activemq.artemis.api.core.FilterConstants.NATIVE_MESSAGE_ID;
|
||||||
|
|
||||||
import javax.management.InstanceNotFoundException;
|
import javax.management.InstanceNotFoundException;
|
||||||
import javax.management.MBeanRegistrationException;
|
import javax.management.MBeanRegistrationException;
|
||||||
import javax.management.MBeanServer;
|
import javax.management.MBeanServer;
|
||||||
|
@ -390,6 +392,11 @@ public class ManagementServiceImpl implements ManagementService {
|
||||||
reply.setType(Message.TEXT_TYPE);
|
reply.setType(Message.TEXT_TYPE);
|
||||||
reply.setReplyTo(message.getReplyTo());
|
reply.setReplyTo(message.getReplyTo());
|
||||||
|
|
||||||
|
Object correlationID = getCorrelationIdentity(message);
|
||||||
|
if (correlationID != null) {
|
||||||
|
reply.setCorrelationID(correlationID);
|
||||||
|
}
|
||||||
|
|
||||||
String resourceName = message.getStringProperty(ManagementHelper.HDR_RESOURCE_NAME);
|
String resourceName = message.getStringProperty(ManagementHelper.HDR_RESOURCE_NAME);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("handling management message for " + resourceName);
|
logger.debug("handling management message for " + resourceName);
|
||||||
|
@ -781,5 +788,24 @@ public class ManagementServiceImpl implements ManagementService {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correlate management responses using the Correlation ID Pattern, if the request supplied a correlation id,
|
||||||
|
* or fallback to the Message ID Pattern providing the request had a message id.
|
||||||
|
|
||||||
|
* @param request
|
||||||
|
* @return correlation identify
|
||||||
|
*/
|
||||||
|
private Object getCorrelationIdentity(final Message request) {
|
||||||
|
Object correlationId = request.getCorrelationID();
|
||||||
|
if (correlationId == null) {
|
||||||
|
// CoreMessage#getUserId returns UUID, so to implement this part a alternative API that returned object. This part of the
|
||||||
|
// change is a nice to have for my point of view. I suggested it for completeness. The application could
|
||||||
|
// always supply unique correl ids on the request and achieve the same effect. I'd be happy to drop this part.
|
||||||
|
Object underlying = request.getUserID() != null ? request.getUserID() : request.getStringProperty(NATIVE_MESSAGE_ID);
|
||||||
|
correlationId = underlying == null ? null : String.valueOf(underlying);
|
||||||
|
}
|
||||||
|
return correlationId;
|
||||||
|
}
|
||||||
|
|
||||||
// Inner classes -------------------------------------------------
|
// Inner classes -------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.activemq.artemis.tests.integration.amqp;
|
package org.apache.activemq.artemis.tests.integration.amqp;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.activemq.artemis.api.core.management.ResourceNames;
|
import org.apache.activemq.artemis.api.core.management.ResourceNames;
|
||||||
|
@ -27,6 +29,8 @@ import org.apache.activemq.transport.amqp.client.AmqpMessage;
|
||||||
import org.apache.activemq.transport.amqp.client.AmqpReceiver;
|
import org.apache.activemq.transport.amqp.client.AmqpReceiver;
|
||||||
import org.apache.activemq.transport.amqp.client.AmqpSender;
|
import org.apache.activemq.transport.amqp.client.AmqpSender;
|
||||||
import org.apache.activemq.transport.amqp.client.AmqpSession;
|
import org.apache.activemq.transport.amqp.client.AmqpSession;
|
||||||
|
|
||||||
|
import org.apache.qpid.proton.amqp.Binary;
|
||||||
import org.apache.qpid.proton.amqp.UnsignedByte;
|
import org.apache.qpid.proton.amqp.UnsignedByte;
|
||||||
import org.apache.qpid.proton.amqp.UnsignedInteger;
|
import org.apache.qpid.proton.amqp.UnsignedInteger;
|
||||||
import org.apache.qpid.proton.amqp.UnsignedLong;
|
import org.apache.qpid.proton.amqp.UnsignedLong;
|
||||||
|
@ -39,6 +43,8 @@ import static org.apache.activemq.artemis.protocol.amqp.converter.AMQPMessageSup
|
||||||
|
|
||||||
public class AmqpManagementTest extends AmqpClientTestSupport {
|
public class AmqpManagementTest extends AmqpClientTestSupport {
|
||||||
|
|
||||||
|
private static final Binary BINARY_CORRELATION_ID = new Binary("mystring".getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
@Test(timeout = 60000)
|
@Test(timeout = 60000)
|
||||||
public void testManagementQueryOverAMQP() throws Throwable {
|
public void testManagementQueryOverAMQP() throws Throwable {
|
||||||
AmqpClient client = createAmqpClient();
|
AmqpClient client = createAmqpClient();
|
||||||
|
@ -101,4 +107,67 @@ public class AmqpManagementTest extends AmqpClientTestSupport {
|
||||||
msg = createMapMessage(1, map, null);
|
msg = createMapMessage(1, map, null);
|
||||||
assertEquals(msg.getByte("sequence"), sequence);
|
assertEquals(msg.getByte("sequence"), sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 60000)
|
||||||
|
public void testCorrelationByMessageIDUUID() throws Throwable {
|
||||||
|
doTestReplyCorrelation(UUID.randomUUID(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 60000)
|
||||||
|
public void testCorrelationByMessageIDString() throws Throwable {
|
||||||
|
doTestReplyCorrelation("mystring", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 60000)
|
||||||
|
public void testCorrelationByMessageIDBinary() throws Throwable {
|
||||||
|
doTestReplyCorrelation(BINARY_CORRELATION_ID, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 60000)
|
||||||
|
public void testCorrelationByCorrelationIDUUID() throws Throwable {
|
||||||
|
doTestReplyCorrelation(UUID.randomUUID(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 60000)
|
||||||
|
public void testCorrelationByCorrelationIDString() throws Throwable {
|
||||||
|
doTestReplyCorrelation("mystring", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 60000)
|
||||||
|
public void testCorrelationByCorrelationIDBinary() throws Throwable {
|
||||||
|
doTestReplyCorrelation(BINARY_CORRELATION_ID, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doTestReplyCorrelation(final Object correlationId, final boolean sendCorrelAsCorrelation) throws Exception {
|
||||||
|
AmqpClient client = createAmqpClient();
|
||||||
|
AmqpConnection connection = addConnection(client.connect());
|
||||||
|
|
||||||
|
try {
|
||||||
|
String destinationAddress = getQueueName(1);
|
||||||
|
AmqpSession session = connection.createSession();
|
||||||
|
AmqpSender sender = session.createSender("activemq.management");
|
||||||
|
AmqpReceiver receiver = session.createReceiver(destinationAddress);
|
||||||
|
receiver.flow(10);
|
||||||
|
|
||||||
|
// Create request message for getQueueNames query
|
||||||
|
AmqpMessage request = new AmqpMessage();
|
||||||
|
request.setApplicationProperty("_AMQ_ResourceName", ResourceNames.BROKER);
|
||||||
|
request.setApplicationProperty("_AMQ_OperationName", "getQueueNames");
|
||||||
|
request.setReplyToAddress(destinationAddress);
|
||||||
|
if (sendCorrelAsCorrelation) {
|
||||||
|
request.setRawCorrelationId(correlationId);
|
||||||
|
} else {
|
||||||
|
request.setRawMessageId(correlationId);
|
||||||
|
}
|
||||||
|
request.setText("[]");
|
||||||
|
|
||||||
|
sender.send(request);
|
||||||
|
AmqpMessage response = receiver.receive(5, TimeUnit.SECONDS);
|
||||||
|
Assert.assertNotNull(response);
|
||||||
|
Assert.assertEquals(correlationId, response.getRawCorrelationId());
|
||||||
|
response.accept();
|
||||||
|
} finally {
|
||||||
|
connection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,10 +31,13 @@ import org.apache.activemq.artemis.core.server.ActiveMQServers;
|
||||||
import org.apache.activemq.artemis.core.server.Queue;
|
import org.apache.activemq.artemis.core.server.Queue;
|
||||||
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
|
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
|
||||||
import org.apache.activemq.artemis.core.server.management.impl.ManagementServiceImpl;
|
import org.apache.activemq.artemis.core.server.management.impl.ManagementServiceImpl;
|
||||||
|
import org.apache.activemq.artemis.reader.MessageUtil;
|
||||||
import org.apache.activemq.artemis.tests.integration.server.FakeStorageManager;
|
import org.apache.activemq.artemis.tests.integration.server.FakeStorageManager;
|
||||||
import org.apache.activemq.artemis.tests.unit.core.postoffice.impl.FakeQueue;
|
import org.apache.activemq.artemis.tests.unit.core.postoffice.impl.FakeQueue;
|
||||||
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
|
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
|
||||||
import org.apache.activemq.artemis.utils.RandomUtil;
|
import org.apache.activemq.artemis.utils.RandomUtil;
|
||||||
|
import org.apache.activemq.artemis.utils.UUID;
|
||||||
|
import org.apache.activemq.artemis.utils.UUIDGenerator;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -153,6 +156,49 @@ public class ManagementServiceImplTest extends ActiveMQTestBase {
|
||||||
Assert.assertEquals(queue.getName().toString(), queueControl.getName());
|
Assert.assertEquals(queue.getName().toString(), queueControl.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCorrelateResponseByCorrelationID() throws Exception {
|
||||||
|
String queue = RandomUtil.randomString();
|
||||||
|
String address = RandomUtil.randomString();
|
||||||
|
String correlationID = UUIDGenerator.getInstance().generateStringUUID();
|
||||||
|
|
||||||
|
Configuration config = createBasicConfig().setJMXManagementEnabled(false);
|
||||||
|
|
||||||
|
ActiveMQServer server = addServer(ActiveMQServers.newActiveMQServer(config, false));
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
// invoke attribute and operation on the server
|
||||||
|
CoreMessage message = new CoreMessage(1, 100);
|
||||||
|
MessageUtil.setJMSCorrelationID(message, correlationID);
|
||||||
|
ManagementHelper.putOperationInvocation(message, ResourceNames.BROKER, "createQueue", queue, address);
|
||||||
|
|
||||||
|
Message reply = server.getManagementService().handleMessage(message);
|
||||||
|
Assert.assertTrue(ManagementHelper.hasOperationSucceeded(reply));
|
||||||
|
Assert.assertEquals(correlationID, MessageUtil.getJMSCorrelationID(reply));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCorrelateResponseByMessageID() throws Exception {
|
||||||
|
String queue = RandomUtil.randomString();
|
||||||
|
String address = RandomUtil.randomString();
|
||||||
|
UUID messageId = UUIDGenerator.getInstance().generateUUID();
|
||||||
|
|
||||||
|
Configuration config = createBasicConfig().setJMXManagementEnabled(false);
|
||||||
|
|
||||||
|
ActiveMQServer server = addServer(ActiveMQServers.newActiveMQServer(config, false));
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
// invoke attribute and operation on the server
|
||||||
|
CoreMessage message = new CoreMessage(1, 100);
|
||||||
|
message.setUserID(messageId);
|
||||||
|
ManagementHelper.putOperationInvocation(message, ResourceNames.BROKER, "createQueue", queue, address);
|
||||||
|
|
||||||
|
Message reply = server.getManagementService().handleMessage(message);
|
||||||
|
Assert.assertTrue(ManagementHelper.hasOperationSucceeded(reply));
|
||||||
|
Assert.assertEquals(messageId.toString(), MessageUtil.getJMSCorrelationID(reply));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Package protected ---------------------------------------------
|
// Package protected ---------------------------------------------
|
||||||
|
|
||||||
// Protected -----------------------------------------------------
|
// Protected -----------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue