ARTEMIS-788 Stomp refactor + track autocreation for addresses
This commit is contained in:
parent
0189f156ec
commit
a88853fe53
|
@ -550,11 +550,11 @@ public class ArtemisTest {
|
|||
ClientSessionFactory factory = locator.createSessionFactory();
|
||||
ClientSession coreSession = factory.createSession("admin", "admin", false, true, true, false, 0)) {
|
||||
for (String str : queues.split(",")) {
|
||||
ClientSession.QueueQuery queryResult = coreSession.queueQuery(SimpleString.toSimpleString("jms.queue." + str));
|
||||
ClientSession.QueueQuery queryResult = coreSession.queueQuery(SimpleString.toSimpleString(str));
|
||||
assertTrue("Couldn't find queue " + str, queryResult.isExists());
|
||||
}
|
||||
for (String str : topics.split(",")) {
|
||||
ClientSession.QueueQuery queryResult = coreSession.queueQuery(SimpleString.toSimpleString("jms.topic." + str));
|
||||
ClientSession.QueueQuery queryResult = coreSession.queueQuery(SimpleString.toSimpleString(str));
|
||||
assertTrue("Couldn't find topic " + str, queryResult.isExists());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -198,7 +198,7 @@ public interface ClientSession extends XAResource, AutoCloseable {
|
|||
*/
|
||||
int getVersion();
|
||||
|
||||
void createAddress(final SimpleString address, final boolean multicast) throws ActiveMQException;
|
||||
void createAddress(final SimpleString address, final boolean multicast, final boolean autoCreated) throws ActiveMQException;
|
||||
|
||||
// Queue Operations ----------------------------------------------
|
||||
|
||||
|
|
|
@ -279,12 +279,12 @@ public final class ClientSessionImpl implements ClientSessionInternal, FailureLi
|
|||
}
|
||||
|
||||
@Override
|
||||
public void createAddress(final SimpleString address, final boolean multicast) throws ActiveMQException {
|
||||
public void createAddress(final SimpleString address, final boolean multicast, boolean autoCreated) throws ActiveMQException {
|
||||
checkClosed();
|
||||
|
||||
startCall();
|
||||
try {
|
||||
sessionContext.createAddress(address, multicast);
|
||||
sessionContext.createAddress(address, multicast, autoCreated);
|
||||
} finally {
|
||||
endCall();
|
||||
}
|
||||
|
|
|
@ -584,8 +584,8 @@ public class ActiveMQSessionContext extends SessionContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void createAddress(SimpleString address, final boolean multicast) throws ActiveMQException {
|
||||
CreateAddressMessage request = new CreateAddressMessage(address, multicast, true);
|
||||
public void createAddress(SimpleString address, final boolean multicast, final boolean autoCreated) throws ActiveMQException {
|
||||
CreateAddressMessage request = new CreateAddressMessage(address, multicast, autoCreated, true);
|
||||
sessionChannel.sendBlocking(request, PacketImpl.NULL_RESPONSE);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,15 +26,19 @@ public class CreateAddressMessage extends PacketImpl {
|
|||
|
||||
private boolean multicast;
|
||||
|
||||
private boolean autoCreated;
|
||||
|
||||
private boolean requiresResponse;
|
||||
|
||||
public CreateAddressMessage(final SimpleString address,
|
||||
final boolean multicast,
|
||||
final boolean autoCreated,
|
||||
final boolean requiresResponse) {
|
||||
this();
|
||||
|
||||
this.address = address;
|
||||
this.multicast = multicast;
|
||||
this.autoCreated = autoCreated;
|
||||
this.requiresResponse = requiresResponse;
|
||||
}
|
||||
|
||||
|
@ -49,6 +53,7 @@ public class CreateAddressMessage extends PacketImpl {
|
|||
StringBuffer buff = new StringBuffer(getParentString());
|
||||
buff.append(", address=" + address);
|
||||
buff.append(", multicast=" + multicast);
|
||||
buff.append(", autoCreated=" + autoCreated);
|
||||
buff.append("]");
|
||||
return buff.toString();
|
||||
}
|
||||
|
@ -65,6 +70,10 @@ public class CreateAddressMessage extends PacketImpl {
|
|||
return requiresResponse;
|
||||
}
|
||||
|
||||
public boolean isAutoCreated() {
|
||||
return autoCreated;
|
||||
}
|
||||
|
||||
public void setAddress(SimpleString address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
@ -74,6 +83,7 @@ public class CreateAddressMessage extends PacketImpl {
|
|||
buffer.writeSimpleString(address);
|
||||
buffer.writeBoolean(multicast);
|
||||
buffer.writeBoolean(requiresResponse);
|
||||
buffer.writeBoolean(autoCreated);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -81,6 +91,7 @@ public class CreateAddressMessage extends PacketImpl {
|
|||
address = buffer.readSimpleString();
|
||||
multicast = buffer.readBoolean();
|
||||
requiresResponse = buffer.readBoolean();
|
||||
autoCreated = buffer.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -89,6 +100,7 @@ public class CreateAddressMessage extends PacketImpl {
|
|||
int result = super.hashCode();
|
||||
result = prime * result + ((address == null) ? 0 : address.hashCode());
|
||||
result = prime * result + (multicast ? 1231 : 1237);
|
||||
result = prime * result + (autoCreated ? 1231 : 1237);
|
||||
result = prime * result + (requiresResponse ? 1231 : 1237);
|
||||
return result;
|
||||
}
|
||||
|
@ -109,6 +121,8 @@ public class CreateAddressMessage extends PacketImpl {
|
|||
return false;
|
||||
if (multicast != other.multicast)
|
||||
return false;
|
||||
if (autoCreated != other.autoCreated)
|
||||
return false;
|
||||
if (requiresResponse != other.requiresResponse)
|
||||
return false;
|
||||
return true;
|
||||
|
|
|
@ -203,6 +203,14 @@ public class TransportConstants {
|
|||
|
||||
public static final String STOMP_MIN_LARGE_MESSAGE_SIZE = "stomp-min-large-message-size";
|
||||
|
||||
public static final String STOMP_ANYCAST_PREFIX = "stompAnycastPrefix";
|
||||
|
||||
public static final String DEFAULT_STOMP_ANYCAST_PREFIX = "";
|
||||
|
||||
public static final String STOMP_MULTICAST_PREFIX = "stompMulticastPrefix";
|
||||
|
||||
public static final String DEFAULT_STOMP_MULTICAST_PREFIX = "";
|
||||
|
||||
public static final String NETTY_CONNECT_TIMEOUT = "connect-timeout-millis";
|
||||
|
||||
public static final int DEFAULT_NETTY_CONNECT_TIMEOUT = -1;
|
||||
|
@ -242,6 +250,8 @@ public class TransportConstants {
|
|||
allowableAcceptorKeys.add(TransportConstants.CLUSTER_CONNECTION);
|
||||
allowableAcceptorKeys.add(TransportConstants.STOMP_CONSUMERS_CREDIT);
|
||||
allowableAcceptorKeys.add(TransportConstants.STOMP_MIN_LARGE_MESSAGE_SIZE);
|
||||
allowableAcceptorKeys.add(TransportConstants.STOMP_ANYCAST_PREFIX);
|
||||
allowableAcceptorKeys.add(TransportConstants.STOMP_MULTICAST_PREFIX);
|
||||
allowableAcceptorKeys.add(TransportConstants.CONNECTION_TTL);
|
||||
allowableAcceptorKeys.add(TransportConstants.CONNECTION_TTL_MAX);
|
||||
allowableAcceptorKeys.add(TransportConstants.CONNECTION_TTL_MIN);
|
||||
|
|
|
@ -166,7 +166,7 @@ public abstract class SessionContext {
|
|||
|
||||
public abstract void deleteQueue(SimpleString queueName) throws ActiveMQException;
|
||||
|
||||
public abstract void createAddress(SimpleString address, boolean multicast) throws ActiveMQException;
|
||||
public abstract void createAddress(SimpleString address, boolean multicast, boolean autoCreated) throws ActiveMQException;
|
||||
|
||||
public abstract void createQueue(SimpleString address,
|
||||
SimpleString queueName,
|
||||
|
|
|
@ -403,20 +403,20 @@ public class ActiveMQMessageProducer implements MessageProducer, QueueSender, To
|
|||
try {
|
||||
ClientSession.AddressQuery query = clientSession.addressQuery(address);
|
||||
|
||||
if (!query.isExists() && query.isAutoCreateJmsQueues()) {
|
||||
if (destination.isQueue() && !destination.isTemporary()) {
|
||||
clientSession.createAddress(address, false);
|
||||
clientSession.createQueue(address, address, null, true);
|
||||
} else if (destination.isQueue() && destination.isTemporary()) {
|
||||
clientSession.createAddress(address, false);
|
||||
clientSession.createTemporaryQueue(address, address);
|
||||
} else if (!destination.isQueue() && !destination.isTemporary()) {
|
||||
clientSession.createAddress(address, true);
|
||||
} else if (!destination.isQueue() && destination.isTemporary()) {
|
||||
clientSession.createAddress(address, true);
|
||||
if (!query.isExists()) {
|
||||
if (destination.isQueue() && query.isAutoCreateJmsQueues()) {
|
||||
clientSession.createAddress(address, false, true);
|
||||
if (destination.isTemporary()) {
|
||||
// TODO is it right to use the address for the queue name here?
|
||||
clientSession.createTemporaryQueue(address, address);
|
||||
} else {
|
||||
clientSession.createQueue(address, address, null, true);
|
||||
}
|
||||
} else if (!destination.isQueue() && query.isAutoCreateJmsTopics()) {
|
||||
clientSession.createAddress(address, true, true);
|
||||
} else if ((destination.isQueue() && !query.isAutoCreateJmsQueues()) || (!destination.isQueue() && !query.isAutoCreateJmsTopics())) {
|
||||
throw new InvalidDestinationException("Destination " + address + " does not exist");
|
||||
}
|
||||
} else if (!query.isExists() && !query.isAutoCreateJmsQueues()) {
|
||||
throw new InvalidDestinationException("Destination " + address + " does not exist");
|
||||
} else {
|
||||
connection.addKnownDestination(address);
|
||||
}
|
||||
|
|
|
@ -299,29 +299,16 @@ public class ActiveMQSession implements QueueSession, TopicSession {
|
|||
if (jbd != null) {
|
||||
ClientSession.AddressQuery response = session.addressQuery(jbd.getSimpleAddress());
|
||||
|
||||
if (jbd.isQueue()) {
|
||||
if (!response.isExists()) {
|
||||
if (response.isAutoCreateJmsQueues()) {
|
||||
session.createAddress(jbd.getSimpleAddress(), false);
|
||||
} else {
|
||||
throw new InvalidDestinationException("Destination " + jbd.getName() + " does not exist");
|
||||
}
|
||||
}
|
||||
|
||||
if (response.getQueueNames().isEmpty()) {
|
||||
if (response.isAutoCreateJmsQueues()) {
|
||||
session.createQueue(jbd.getSimpleAddress(), jbd.getSimpleAddress(), null, true);
|
||||
} else {
|
||||
throw new InvalidDestinationException("Destination " + jbd.getName() + " does not exist");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!response.isExists()) {
|
||||
if (response.isAutoCreateJmsTopics()) {
|
||||
session.createAddress(jbd.getSimpleAddress(), true);
|
||||
} else {
|
||||
throw new InvalidDestinationException("Destination " + jbd.getName() + " does not exist");
|
||||
}
|
||||
if (!response.isExists()) {
|
||||
if (jbd.isQueue() && response.isAutoCreateJmsQueues()) {
|
||||
// TODO create queue here in such a way that it is deleted when consumerCount == 0
|
||||
// perhaps just relying on the broker to do it is simplest (i.e. deleteOnNoConsumers)
|
||||
session.createAddress(jbd.getSimpleAddress(), false, true);
|
||||
session.createQueue(jbd.getSimpleAddress(), jbd.getSimpleAddress(), null, true);
|
||||
} else if (!jbd.isQueue() && response.isAutoCreateJmsTopics()) {
|
||||
session.createAddress(jbd.getSimpleAddress(), true, true);
|
||||
} else {
|
||||
throw new InvalidDestinationException("Destination " + jbd.getName() + " does not exist");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -660,6 +647,8 @@ public class ActiveMQSession implements QueueSession, TopicSession {
|
|||
*/
|
||||
if (!response.isExists() || !response.getQueueNames().contains(dest.getSimpleAddress())) {
|
||||
if (response.isAutoCreateJmsQueues()) {
|
||||
// TODO create queue here in such a way that it is deleted when consumerCount == 0
|
||||
// perhaps just relying on the broker to do it is simplest (i.e. deleteOnNoConsumers)
|
||||
session.createQueue(dest.getSimpleAddress(), dest.getSimpleAddress(), true);
|
||||
} else {
|
||||
throw new InvalidDestinationException("Destination " + dest.getName() + " does not exist");
|
||||
|
@ -673,8 +662,8 @@ public class ActiveMQSession implements QueueSession, TopicSession {
|
|||
AddressQuery response = session.addressQuery(dest.getSimpleAddress());
|
||||
|
||||
if (!response.isExists()) {
|
||||
if (response.isAutoCreateJmsQueues()) {
|
||||
session.createAddress(dest.getSimpleAddress(), true);
|
||||
if (response.isAutoCreateJmsTopics()) {
|
||||
session.createAddress(dest.getSimpleAddress(), true, true);
|
||||
} else {
|
||||
throw new InvalidDestinationException("Topic " + dest.getName() + " does not exist");
|
||||
}
|
||||
|
@ -1106,7 +1095,7 @@ public class ActiveMQSession implements QueueSession, TopicSession {
|
|||
|
||||
AddressQuery query = session.addressQuery(topic.getSimpleAddress());
|
||||
|
||||
if (!query.isExists() && !query.isAutoCreateJmsQueues()) {
|
||||
if (!query.isExists() && !query.isAutoCreateJmsTopics()) {
|
||||
return null;
|
||||
} else {
|
||||
return topic;
|
||||
|
|
|
@ -93,7 +93,7 @@ public class MQTTSubscriptionManager {
|
|||
|
||||
Queue q = session.getServer().locateQueue(queue);
|
||||
if (q == null) {
|
||||
q = session.getServerSession().createQueue(new SimpleString(address), queue, managementFilter, false, MQTTUtil.DURABLE_MESSAGES && qos >= 0, -1, false);
|
||||
q = session.getServerSession().createQueue(new SimpleString(address), queue, managementFilter, false, MQTTUtil.DURABLE_MESSAGES && qos >= 0, -1, false, true);
|
||||
} else {
|
||||
if (q.isDeleteOnNoConsumers()) {
|
||||
throw ActiveMQMessageBundle.BUNDLE.invalidQueueConfiguration(q.getAddress(), q.getName(), "deleteOnNoConsumers", false, true);
|
||||
|
|
|
@ -41,12 +41,12 @@ public class ActiveMQStompException extends Exception {
|
|||
}
|
||||
|
||||
public ActiveMQStompException(String msg) {
|
||||
super(msg);
|
||||
super(msg.replace(":", ""));
|
||||
handler = null;
|
||||
}
|
||||
|
||||
public ActiveMQStompException(String msg, Throwable t) {
|
||||
super(msg, t);
|
||||
super(msg.replace(":", ""), t);
|
||||
this.body = t.getMessage();
|
||||
handler = null;
|
||||
}
|
||||
|
|
|
@ -86,10 +86,10 @@ public interface ActiveMQStompProtocolMessageBundle {
|
|||
ActiveMQStompException noDestination();
|
||||
|
||||
@Message(id = 339016, value = "Error creating subscription {0}", format = Message.Format.MESSAGE_FORMAT)
|
||||
ActiveMQStompException errorCreatSubscription(String subscriptionID, @Cause Exception e);
|
||||
ActiveMQStompException errorCreatingSubscription(String subscriptionID, @Cause Exception e);
|
||||
|
||||
@Message(id = 339017, value = "Error unsubscribing {0}", format = Message.Format.MESSAGE_FORMAT)
|
||||
ActiveMQStompException errorUnsubscrib(String subscriptionID, @Cause Exception e);
|
||||
ActiveMQStompException errorUnsubscribing(String subscriptionID, @Cause Exception e);
|
||||
|
||||
@Message(id = 339018, value = "Error acknowledging message {0}", format = Message.Format.MESSAGE_FORMAT)
|
||||
ActiveMQStompException errorAck(String messageID, @Cause Exception e);
|
||||
|
@ -153,4 +153,7 @@ public interface ActiveMQStompProtocolMessageBundle {
|
|||
|
||||
@Message(id = 339040, value = "Undefined escape sequence: {0}", format = Message.Format.MESSAGE_FORMAT)
|
||||
ActiveMQStompException undefinedEscapeSequence(String sequence);
|
||||
|
||||
@Message(id = 339041, value = "Not allowed to specify {0} semantics on {1} address.", format = Message.Format.MESSAGE_FORMAT)
|
||||
ActiveMQStompException illegalSemantics(String requested, String exists);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@ package org.apache.activemq.artemis.core.protocol.stomp;
|
|||
|
||||
/**
|
||||
* The standard verbs and headers used for the <a href="http://stomp.codehaus.org/">STOMP</a> protocol.
|
||||
*
|
||||
* @version $Revision: 57 $
|
||||
*/
|
||||
public interface Stomp {
|
||||
|
||||
|
@ -27,7 +25,7 @@ public interface Stomp {
|
|||
|
||||
String NEWLINE = "\n";
|
||||
|
||||
public interface Commands {
|
||||
interface Commands {
|
||||
|
||||
String CONNECT = "CONNECT";
|
||||
|
||||
|
@ -53,7 +51,7 @@ public interface Stomp {
|
|||
String STOMP = "STOMP";
|
||||
}
|
||||
|
||||
public interface Responses {
|
||||
interface Responses {
|
||||
|
||||
String CONNECTED = "CONNECTED";
|
||||
|
||||
|
@ -64,7 +62,7 @@ public interface Stomp {
|
|||
String RECEIPT = "RECEIPT";
|
||||
}
|
||||
|
||||
public interface Headers {
|
||||
interface Headers {
|
||||
|
||||
String SEPARATOR = ":";
|
||||
|
||||
|
@ -78,15 +76,17 @@ public interface Stomp {
|
|||
|
||||
String CONTENT_TYPE = "content-type";
|
||||
|
||||
public interface Response {
|
||||
interface Response {
|
||||
|
||||
String RECEIPT_ID = "receipt-id";
|
||||
}
|
||||
|
||||
public interface Send {
|
||||
interface Send {
|
||||
|
||||
String DESTINATION = "destination";
|
||||
|
||||
String DESTINATION_TYPE = "destination-type";
|
||||
|
||||
String CORRELATION_ID = "correlation-id";
|
||||
|
||||
String REPLY_TO = "reply-to";
|
||||
|
@ -97,10 +97,10 @@ public interface Stomp {
|
|||
|
||||
String TYPE = "type";
|
||||
|
||||
Object PERSISTENT = "persistent";
|
||||
String PERSISTENT = "persistent";
|
||||
}
|
||||
|
||||
public interface Message {
|
||||
interface Message {
|
||||
|
||||
String MESSAGE_ID = "message-id";
|
||||
|
||||
|
@ -129,7 +129,7 @@ public interface Stomp {
|
|||
String VALIDATED_USER = "JMSXUserID";
|
||||
}
|
||||
|
||||
public interface Subscribe {
|
||||
interface Subscribe {
|
||||
|
||||
String DESTINATION = "destination";
|
||||
|
||||
|
@ -144,6 +144,8 @@ public interface Stomp {
|
|||
|
||||
String DURABLE_SUBSCRIPTION_NAME = "durable-subscription-name";
|
||||
|
||||
String SUBSCRIPTION_TYPE = "subscription-type";
|
||||
|
||||
String NO_LOCAL = "no-local";
|
||||
|
||||
public interface AckModeValues {
|
||||
|
@ -156,7 +158,7 @@ public interface Stomp {
|
|||
}
|
||||
}
|
||||
|
||||
public interface Unsubscribe {
|
||||
interface Unsubscribe {
|
||||
|
||||
String DESTINATION = "destination";
|
||||
|
||||
|
@ -168,7 +170,7 @@ public interface Stomp {
|
|||
String DURABLE_SUBSCRIPTION_NAME = "durable-subscription-name";
|
||||
}
|
||||
|
||||
public interface Connect {
|
||||
interface Connect {
|
||||
|
||||
String LOGIN = "login";
|
||||
|
||||
|
@ -182,10 +184,10 @@ public interface Stomp {
|
|||
String ACCEPT_VERSION = "accept-version";
|
||||
String HOST = "host";
|
||||
|
||||
Object HEART_BEAT = "heart-beat";
|
||||
String HEART_BEAT = "heart-beat";
|
||||
}
|
||||
|
||||
public interface Error {
|
||||
interface Error {
|
||||
|
||||
String MESSAGE = "message";
|
||||
|
||||
|
@ -193,7 +195,7 @@ public interface Stomp {
|
|||
String VERSION = "version";
|
||||
}
|
||||
|
||||
public interface Connected {
|
||||
interface Connected {
|
||||
|
||||
String SESSION = "session";
|
||||
|
||||
|
@ -207,7 +209,7 @@ public interface Stomp {
|
|||
String HEART_BEAT = "heart-beat";
|
||||
}
|
||||
|
||||
public interface Ack {
|
||||
interface Ack {
|
||||
|
||||
String MESSAGE_ID = "message-id";
|
||||
|
||||
|
|
|
@ -86,6 +86,12 @@ public final class StompConnection implements RemotingConnection {
|
|||
|
||||
private final boolean enableMessageID;
|
||||
|
||||
private final int minLargeMessageSize;
|
||||
|
||||
private final String anycastPrefix;
|
||||
|
||||
private final String multicastPrefix;
|
||||
|
||||
private StompVersions version;
|
||||
|
||||
private VersionedStompFrameHandler frameHandler;
|
||||
|
@ -97,8 +103,6 @@ public final class StompConnection implements RemotingConnection {
|
|||
|
||||
private final Object sendLock = new Object();
|
||||
|
||||
private final int minLargeMessageSize;
|
||||
|
||||
private final ScheduledExecutorService scheduledExecutorService;
|
||||
|
||||
private final ExecutorFactory factory;
|
||||
|
@ -162,6 +166,8 @@ public final class StompConnection implements RemotingConnection {
|
|||
|
||||
this.enableMessageID = ConfigurationHelper.getBooleanProperty(TransportConstants.STOMP_ENABLE_MESSAGE_ID, false, acceptorUsed.getConfiguration());
|
||||
this.minLargeMessageSize = ConfigurationHelper.getIntProperty(TransportConstants.STOMP_MIN_LARGE_MESSAGE_SIZE, ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, acceptorUsed.getConfiguration());
|
||||
this.anycastPrefix = ConfigurationHelper.getStringProperty(TransportConstants.STOMP_ANYCAST_PREFIX, TransportConstants.DEFAULT_STOMP_ANYCAST_PREFIX, acceptorUsed.getConfiguration());
|
||||
this.multicastPrefix = ConfigurationHelper.getStringProperty(TransportConstants.STOMP_MULTICAST_PREFIX, TransportConstants.DEFAULT_STOMP_MULTICAST_PREFIX, acceptorUsed.getConfiguration());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -246,23 +252,39 @@ public final class StompConnection implements RemotingConnection {
|
|||
}
|
||||
|
||||
public void checkDestination(String destination) throws ActiveMQStompException {
|
||||
autoCreateDestinationIfPossible(destination);
|
||||
|
||||
if (!manager.destinationExists(destination)) {
|
||||
throw BUNDLE.destinationNotExist(destination).setHandler(frameHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public void autoCreateDestinationIfPossible(String queue) throws ActiveMQStompException {
|
||||
// TODO: STOMP clients will have to prefix their destination with queue:// or topic:// so we can determine what to do here
|
||||
public boolean autoCreateDestinationIfPossible(String queue, AddressInfo.RoutingType routingType) throws ActiveMQStompException {
|
||||
boolean result = false;
|
||||
|
||||
try {
|
||||
manager.getServer().createOrUpdateAddressInfo(new AddressInfo(SimpleString.toSimpleString(queue)).setRoutingType(AddressInfo.RoutingType.ANYCAST));
|
||||
manager.getServer().createQueue(SimpleString.toSimpleString(queue), SimpleString.toSimpleString(queue), null, true, false);
|
||||
if (manager.getServer().getAddressInfo(SimpleString.toSimpleString(queue)) == null) {
|
||||
// TODO check here to see if auto-creation is enabled
|
||||
if (routingType.equals(AddressInfo.RoutingType.MULTICAST)) {
|
||||
manager.getServer().createOrUpdateAddressInfo(new AddressInfo(SimpleString.toSimpleString(queue)).setAutoCreated(true));
|
||||
} else {
|
||||
manager.getServer().createOrUpdateAddressInfo(new AddressInfo(SimpleString.toSimpleString(queue)).setRoutingType(AddressInfo.RoutingType.ANYCAST).setAutoCreated(true));
|
||||
manager.getServer().createQueue(SimpleString.toSimpleString(queue), SimpleString.toSimpleString(queue), null, null, true, false, true);
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
} catch (ActiveMQQueueExistsException e) {
|
||||
// ignore
|
||||
} catch (Exception e) {
|
||||
throw new ActiveMQStompException(e.getMessage(), e).setHandler(frameHandler);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void checkRoutingSemantics(String destination, AddressInfo.RoutingType routingType) throws ActiveMQStompException {
|
||||
AddressInfo.RoutingType actualRoutingTypeOfAddress = manager.getServer().getAddressInfo(SimpleString.toSimpleString(destination)).getRoutingType();
|
||||
if (routingType != null && !routingType.equals(actualRoutingTypeOfAddress)) {
|
||||
throw BUNDLE.illegalSemantics(routingType.toString(), actualRoutingTypeOfAddress.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -560,7 +582,7 @@ public final class StompConnection implements RemotingConnection {
|
|||
if (stompSession.isNoLocal()) {
|
||||
message.putStringProperty(CONNECTION_ID_PROP, getID().toString());
|
||||
}
|
||||
if (enableMessageID()) {
|
||||
if (isEnableMessageID()) {
|
||||
message.putStringProperty("amqMessageId", "STOMP" + message.getMessageID());
|
||||
}
|
||||
try {
|
||||
|
@ -617,8 +639,11 @@ public final class StompConnection implements RemotingConnection {
|
|||
String ack,
|
||||
String id,
|
||||
String durableSubscriptionName,
|
||||
boolean noLocal) throws ActiveMQStompException {
|
||||
autoCreateDestinationIfPossible(destination);
|
||||
boolean noLocal,
|
||||
AddressInfo.RoutingType subscriptionType) throws ActiveMQStompException {
|
||||
autoCreateDestinationIfPossible(destination, subscriptionType);
|
||||
checkDestination(destination);
|
||||
checkRoutingSemantics(destination, subscriptionType);
|
||||
if (noLocal) {
|
||||
String noLocalFilter = CONNECTION_ID_PROP + " <> '" + getID().toString() + "'";
|
||||
if (selector == null) {
|
||||
|
@ -643,11 +668,11 @@ public final class StompConnection implements RemotingConnection {
|
|||
}
|
||||
|
||||
try {
|
||||
manager.createSubscription(this, subscriptionID, durableSubscriptionName, destination, selector, ack, noLocal);
|
||||
manager.subscribe(this, subscriptionID, durableSubscriptionName, destination, selector, ack, noLocal);
|
||||
} catch (ActiveMQStompException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw BUNDLE.errorCreatSubscription(subscriptionID, e).setHandler(frameHandler);
|
||||
throw BUNDLE.errorCreatingSubscription(subscriptionID, e).setHandler(frameHandler);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -657,7 +682,7 @@ public final class StompConnection implements RemotingConnection {
|
|||
} catch (ActiveMQStompException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw BUNDLE.errorUnsubscrib(subscriptionID, e).setHandler(frameHandler);
|
||||
throw BUNDLE.errorUnsubscribing(subscriptionID, e).setHandler(frameHandler);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -710,7 +735,7 @@ public final class StompConnection implements RemotingConnection {
|
|||
return this.frameHandler;
|
||||
}
|
||||
|
||||
public boolean enableMessageID() {
|
||||
public boolean isEnableMessageID() {
|
||||
return enableMessageID;
|
||||
}
|
||||
|
||||
|
@ -718,6 +743,14 @@ public final class StompConnection implements RemotingConnection {
|
|||
return minLargeMessageSize;
|
||||
}
|
||||
|
||||
public String getAnycastPrefix() {
|
||||
return anycastPrefix;
|
||||
}
|
||||
|
||||
public String getMulticastPrefix() {
|
||||
return multicastPrefix;
|
||||
}
|
||||
|
||||
public StompProtocolManager getManager() {
|
||||
return manager;
|
||||
}
|
||||
|
|
|
@ -368,13 +368,13 @@ public class StompProtocolManager extends AbstractProtocolManager<StompFrame, St
|
|||
}
|
||||
// Inner classes -------------------------------------------------
|
||||
|
||||
public void createSubscription(StompConnection connection,
|
||||
String subscriptionID,
|
||||
String durableSubscriptionName,
|
||||
String destination,
|
||||
String selector,
|
||||
String ack,
|
||||
boolean noLocal) throws Exception {
|
||||
public void subscribe(StompConnection connection,
|
||||
String subscriptionID,
|
||||
String durableSubscriptionName,
|
||||
String destination,
|
||||
String selector,
|
||||
String ack,
|
||||
boolean noLocal) throws Exception {
|
||||
StompSession stompSession = getSession(connection);
|
||||
stompSession.setNoLocal(noLocal);
|
||||
if (stompSession.containsSubscription(subscriptionID)) {
|
||||
|
@ -411,7 +411,7 @@ public class StompProtocolManager extends AbstractProtocolManager<StompFrame, St
|
|||
}
|
||||
|
||||
public boolean destinationExists(String destination) {
|
||||
return server.getPostOffice().getAddresses().contains(SimpleString.toSimpleString(destination));
|
||||
return server.getPostOffice().getAddressInfo(SimpleString.toSimpleString(destination)) != null;
|
||||
}
|
||||
|
||||
public ActiveMQServer getServer() {
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.apache.activemq.artemis.core.protocol.stomp.v10.StompFrameHandlerV10;
|
|||
import org.apache.activemq.artemis.core.protocol.stomp.v11.StompFrameHandlerV11;
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.v12.StompFrameHandlerV12;
|
||||
import org.apache.activemq.artemis.core.server.ServerMessage;
|
||||
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
|
||||
import org.apache.activemq.artemis.core.server.impl.ServerMessageImpl;
|
||||
import org.apache.activemq.artemis.utils.DataConstants;
|
||||
import org.apache.activemq.artemis.utils.ExecutorFactory;
|
||||
|
@ -167,8 +168,11 @@ public abstract class VersionedStompFrameHandler {
|
|||
StompFrame response = null;
|
||||
try {
|
||||
connection.validate();
|
||||
String destination = frame.getHeader(Stomp.Headers.Send.DESTINATION);
|
||||
checkDestination(destination);
|
||||
String destination = getDestination(frame);
|
||||
AddressInfo.RoutingType routingType = getRoutingType(frame.getHeader(Headers.Send.DESTINATION_TYPE), frame.getHeader(Headers.Send.DESTINATION));
|
||||
connection.autoCreateDestinationIfPossible(destination, routingType);
|
||||
connection.checkDestination(destination);
|
||||
connection.checkRoutingSemantics(destination, routingType);
|
||||
String txID = frame.getHeader(Stomp.Headers.TRANSACTION);
|
||||
|
||||
long timestamp = System.currentTimeMillis();
|
||||
|
@ -197,10 +201,6 @@ public abstract class VersionedStompFrameHandler {
|
|||
return response;
|
||||
}
|
||||
|
||||
private void checkDestination(String destination) throws ActiveMQStompException {
|
||||
connection.checkDestination(destination);
|
||||
}
|
||||
|
||||
public StompFrame onBegin(StompFrame frame) {
|
||||
StompFrame response = null;
|
||||
String txID = frame.getHeader(Stomp.Headers.TRANSACTION);
|
||||
|
@ -238,7 +238,7 @@ public abstract class VersionedStompFrameHandler {
|
|||
|
||||
public StompFrame onSubscribe(StompFrame request) {
|
||||
StompFrame response = null;
|
||||
String destination = request.getHeader(Stomp.Headers.Subscribe.DESTINATION);
|
||||
String destination = getDestination(request);
|
||||
|
||||
String selector = request.getHeader(Stomp.Headers.Subscribe.SELECTOR);
|
||||
String ack = request.getHeader(Stomp.Headers.Subscribe.ACK_MODE);
|
||||
|
@ -247,6 +247,7 @@ public abstract class VersionedStompFrameHandler {
|
|||
if (durableSubscriptionName == null) {
|
||||
durableSubscriptionName = request.getHeader(Stomp.Headers.Subscribe.DURABLE_SUBSCRIPTION_NAME);
|
||||
}
|
||||
AddressInfo.RoutingType routingType = getRoutingType(request.getHeader(Headers.Subscribe.SUBSCRIPTION_TYPE), request.getHeader(Headers.Subscribe.DESTINATION));
|
||||
boolean noLocal = false;
|
||||
|
||||
if (request.hasHeader(Stomp.Headers.Subscribe.NO_LOCAL)) {
|
||||
|
@ -254,7 +255,7 @@ public abstract class VersionedStompFrameHandler {
|
|||
}
|
||||
|
||||
try {
|
||||
connection.subscribe(destination, selector, ack, id, durableSubscriptionName, noLocal);
|
||||
connection.subscribe(destination, selector, ack, id, durableSubscriptionName, noLocal, routingType);
|
||||
} catch (ActiveMQStompException e) {
|
||||
response = e.getFrame();
|
||||
}
|
||||
|
@ -262,6 +263,17 @@ public abstract class VersionedStompFrameHandler {
|
|||
return response;
|
||||
}
|
||||
|
||||
public String getDestination(StompFrame request) {
|
||||
String destination = request.getHeader(Headers.Subscribe.DESTINATION);
|
||||
if (connection.getMulticastPrefix().length() > 0 && destination.startsWith(connection.getMulticastPrefix())) {
|
||||
destination = destination.substring(connection.getMulticastPrefix().length());
|
||||
} else if (connection.getAnycastPrefix().length() > 0 && destination.startsWith(connection.getAnycastPrefix())) {
|
||||
destination = destination.substring(connection.getAnycastPrefix().length());
|
||||
}
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
public StompFrame postprocess(StompFrame request) {
|
||||
StompFrame response = null;
|
||||
if (request.hasHeader(Stomp.Headers.RECEIPT_REQUESTED)) {
|
||||
|
@ -332,4 +344,19 @@ public abstract class VersionedStompFrameHandler {
|
|||
connection.destroy();
|
||||
}
|
||||
|
||||
private AddressInfo.RoutingType getRoutingType(String typeHeader, String destination) {
|
||||
// null is valid to return here so we know when the user didn't provide any routing info
|
||||
AddressInfo.RoutingType routingType = null;
|
||||
if (typeHeader != null) {
|
||||
routingType = AddressInfo.RoutingType.valueOf(typeHeader);
|
||||
} else if (destination != null && !connection.getAnycastPrefix().equals(connection.getMulticastPrefix())) {
|
||||
if (connection.getMulticastPrefix().length() > 0 && destination.startsWith(connection.getMulticastPrefix())) {
|
||||
routingType = AddressInfo.RoutingType.MULTICAST;
|
||||
} else if (connection.getAnycastPrefix().length() > 0 && destination.startsWith(connection.getAnycastPrefix())) {
|
||||
routingType = AddressInfo.RoutingType.ANYCAST;
|
||||
}
|
||||
}
|
||||
return routingType;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -276,7 +276,7 @@ public class AddressControlImpl extends AbstractControl implements AddressContro
|
|||
message.getBodyBuffer().writeBytes(Base64.decode(body));
|
||||
}
|
||||
message.setAddress(addressInfo.getName());
|
||||
postOffice.route(message, null, true);
|
||||
postOffice.route(message, true);
|
||||
return "" + message.getMessageID();
|
||||
}
|
||||
|
||||
|
|
|
@ -728,7 +728,7 @@ public class QueueControlImpl extends AbstractControl implements QueueControl {
|
|||
ByteBuffer buffer = ByteBuffer.allocate(8);
|
||||
buffer.putLong(queue.getID());
|
||||
message.putBytesProperty(MessageImpl.HDR_ROUTE_TO_IDS, buffer.array());
|
||||
postOffice.route(message, null, true);
|
||||
postOffice.route(message, true);
|
||||
return "" + message.getMessageID();
|
||||
}
|
||||
|
||||
|
|
|
@ -1268,7 +1268,11 @@ public abstract class AbstractJournalStorageManager implements StorageManager {
|
|||
|
||||
@Override
|
||||
public void addAddressBinding(final long tx, final AddressInfo addressInfo) throws Exception {
|
||||
PersistentAddressBindingEncoding bindingEncoding = new PersistentAddressBindingEncoding(addressInfo.getName(), addressInfo.getRoutingType(), addressInfo.getDefaultMaxQueueConsumers());
|
||||
PersistentAddressBindingEncoding bindingEncoding = new PersistentAddressBindingEncoding(addressInfo.getName(),
|
||||
addressInfo.getRoutingType(),
|
||||
addressInfo.getDefaultMaxQueueConsumers(),
|
||||
addressInfo.isDefaultDeleteOnNoConsumers(),
|
||||
addressInfo.isAutoCreated());
|
||||
|
||||
readLock();
|
||||
try {
|
||||
|
@ -1398,7 +1402,6 @@ public abstract class AbstractJournalStorageManager implements StorageManager {
|
|||
idGenerator.loadState(record.id, buffer);
|
||||
} else if (rec == JournalRecordIds.ADDRESS_BINDING_RECORD) {
|
||||
PersistentAddressBindingEncoding bindingEncoding = newAddressBindingEncoding(id, buffer);
|
||||
ActiveMQServerLogger.LOGGER.info("=== Loading: " + bindingEncoding);
|
||||
addressBindingInfos.add(bindingEncoding);
|
||||
} else if (rec == JournalRecordIds.GROUP_RECORD) {
|
||||
GroupingEncoding encoding = newGroupEncoding(id, buffer);
|
||||
|
|
|
@ -31,6 +31,10 @@ public class PersistentAddressBindingEncoding implements EncodingSupport, Addres
|
|||
|
||||
public int defaultMaxConsumers;
|
||||
|
||||
public boolean defaultDeleteOnNoConsumers;
|
||||
|
||||
public boolean autoCreated;
|
||||
|
||||
public AddressInfo.RoutingType routingType;
|
||||
|
||||
public PersistentAddressBindingEncoding() {
|
||||
|
@ -45,15 +49,23 @@ public class PersistentAddressBindingEncoding implements EncodingSupport, Addres
|
|||
routingType +
|
||||
", defaultMaxConsumers=" +
|
||||
defaultMaxConsumers +
|
||||
", defaultDeleteOnNoConsumers=" +
|
||||
defaultDeleteOnNoConsumers +
|
||||
", autoCreated=" +
|
||||
autoCreated +
|
||||
"]";
|
||||
}
|
||||
|
||||
public PersistentAddressBindingEncoding(final SimpleString name,
|
||||
final AddressInfo.RoutingType routingType,
|
||||
final int defaultMaxConsumers) {
|
||||
final int defaultMaxConsumers,
|
||||
final boolean defaultDeleteOnNoConsumers,
|
||||
final boolean autoCreated) {
|
||||
this.name = name;
|
||||
this.routingType = routingType;
|
||||
this.defaultMaxConsumers = defaultMaxConsumers;
|
||||
this.defaultDeleteOnNoConsumers = defaultDeleteOnNoConsumers;
|
||||
this.autoCreated = autoCreated;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -85,6 +97,8 @@ public class PersistentAddressBindingEncoding implements EncodingSupport, Addres
|
|||
name = buffer.readSimpleString();
|
||||
routingType = AddressInfo.RoutingType.getType(buffer.readByte());
|
||||
defaultMaxConsumers = buffer.readInt();
|
||||
defaultDeleteOnNoConsumers = buffer.readBoolean();
|
||||
autoCreated = buffer.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,10 +106,12 @@ public class PersistentAddressBindingEncoding implements EncodingSupport, Addres
|
|||
buffer.writeSimpleString(name);
|
||||
buffer.writeByte(routingType.getType());
|
||||
buffer.writeInt(defaultMaxConsumers);
|
||||
buffer.writeBoolean(defaultDeleteOnNoConsumers);
|
||||
buffer.writeBoolean(autoCreated);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEncodeSize() {
|
||||
return SimpleString.sizeofString(name) + DataConstants.SIZE_BYTE + DataConstants.SIZE_INT;
|
||||
return SimpleString.sizeofString(name) + DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + DataConstants.SIZE_BOOLEAN + DataConstants.SIZE_BOOLEAN;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import org.apache.activemq.artemis.api.core.SimpleString;
|
|||
import org.apache.activemq.artemis.core.server.ActiveMQComponent;
|
||||
import org.apache.activemq.artemis.core.server.MessageReference;
|
||||
import org.apache.activemq.artemis.core.server.Queue;
|
||||
import org.apache.activemq.artemis.core.server.QueueCreator;
|
||||
import org.apache.activemq.artemis.core.server.RoutingContext;
|
||||
import org.apache.activemq.artemis.core.server.ServerMessage;
|
||||
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
|
||||
|
@ -77,26 +76,22 @@ public interface PostOffice extends ActiveMQComponent {
|
|||
|
||||
Map<SimpleString, Binding> getAllBindings();
|
||||
|
||||
RoutingStatus route(ServerMessage message, QueueCreator queueCreator, boolean direct) throws Exception;
|
||||
RoutingStatus route(ServerMessage message, boolean direct) throws Exception;
|
||||
|
||||
RoutingStatus route(ServerMessage message,
|
||||
QueueCreator queueCreator,
|
||||
Transaction tx,
|
||||
boolean direct) throws Exception;
|
||||
|
||||
RoutingStatus route(ServerMessage message,
|
||||
QueueCreator queueCreator,
|
||||
Transaction tx,
|
||||
boolean direct,
|
||||
boolean rejectDuplicates) throws Exception;
|
||||
|
||||
RoutingStatus route(ServerMessage message,
|
||||
QueueCreator queueCreator,
|
||||
RoutingContext context,
|
||||
boolean direct) throws Exception;
|
||||
|
||||
RoutingStatus route(ServerMessage message,
|
||||
QueueCreator queueCreator,
|
||||
RoutingContext context,
|
||||
boolean direct,
|
||||
boolean rejectDuplicates) throws Exception;
|
||||
|
|
|
@ -63,7 +63,6 @@ import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
|
|||
import org.apache.activemq.artemis.core.server.LargeServerMessage;
|
||||
import org.apache.activemq.artemis.core.server.MessageReference;
|
||||
import org.apache.activemq.artemis.core.server.Queue;
|
||||
import org.apache.activemq.artemis.core.server.QueueCreator;
|
||||
import org.apache.activemq.artemis.core.server.QueueFactory;
|
||||
import org.apache.activemq.artemis.core.server.RouteContextList;
|
||||
import org.apache.activemq.artemis.core.server.RoutingContext;
|
||||
|
@ -441,6 +440,11 @@ public class PostOfficeImpl implements PostOffice, NotificationListener, Binding
|
|||
|
||||
@Override
|
||||
public AddressInfo removeAddressInfo(SimpleString address) {
|
||||
try {
|
||||
getServer().getManagementService().unregisterAddress(address);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return addressManager.removeAddressInfo(address);
|
||||
}
|
||||
|
||||
|
@ -595,39 +599,34 @@ public class PostOfficeImpl implements PostOffice, NotificationListener, Binding
|
|||
|
||||
@Override
|
||||
public RoutingStatus route(final ServerMessage message,
|
||||
QueueCreator queueCreator,
|
||||
final boolean direct) throws Exception {
|
||||
return route(message, queueCreator, (Transaction) null, direct);
|
||||
return route(message, (Transaction) null, direct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoutingStatus route(final ServerMessage message,
|
||||
QueueCreator queueCreator,
|
||||
final Transaction tx,
|
||||
final boolean direct) throws Exception {
|
||||
return route(message, queueCreator, new RoutingContextImpl(tx), direct);
|
||||
return route(message, new RoutingContextImpl(tx), direct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoutingStatus route(final ServerMessage message,
|
||||
final QueueCreator queueCreator,
|
||||
final Transaction tx,
|
||||
final boolean direct,
|
||||
final boolean rejectDuplicates) throws Exception {
|
||||
return route(message, queueCreator, new RoutingContextImpl(tx), direct, rejectDuplicates);
|
||||
return route(message, new RoutingContextImpl(tx), direct, rejectDuplicates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoutingStatus route(final ServerMessage message,
|
||||
final QueueCreator queueCreator,
|
||||
final RoutingContext context,
|
||||
final boolean direct) throws Exception {
|
||||
return route(message, queueCreator, context, direct, true);
|
||||
return route(message, context, direct, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoutingStatus route(final ServerMessage message,
|
||||
final QueueCreator queueCreator,
|
||||
final RoutingContext context,
|
||||
final boolean direct,
|
||||
boolean rejectDuplicates) throws Exception {
|
||||
|
@ -657,14 +656,15 @@ public class PostOfficeImpl implements PostOffice, NotificationListener, Binding
|
|||
|
||||
Bindings bindings = addressManager.getBindingsForRoutingAddress(address);
|
||||
|
||||
// TODO auto-create queues here?
|
||||
// first check for the auto-queue creation thing
|
||||
if (bindings == null && queueCreator != null) {
|
||||
if (bindings == null) {
|
||||
// There is no queue with this address, we will check if it needs to be created
|
||||
if (queueCreator.create(address)) {
|
||||
// if (queueCreator.create(address)) {
|
||||
// TODO: this is not working!!!!
|
||||
// reassign bindings if it was created
|
||||
bindings = addressManager.getBindingsForRoutingAddress(address);
|
||||
}
|
||||
// bindings = addressManager.getBindingsForRoutingAddress(address);
|
||||
// }
|
||||
}
|
||||
|
||||
if (bindings != null) {
|
||||
|
@ -704,7 +704,7 @@ public class PostOfficeImpl implements PostOffice, NotificationListener, Binding
|
|||
|
||||
message.setAddress(dlaAddress);
|
||||
|
||||
route(message, null, context.getTransaction(), false);
|
||||
route(message, context.getTransaction(), false);
|
||||
result = RoutingStatus.NO_BINDINGS_DLA;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -240,30 +240,6 @@ public interface ActiveMQServer extends ActiveMQComponent {
|
|||
|
||||
long getUptimeMillis();
|
||||
|
||||
/**
|
||||
* This is the queue creator responsible for automatic JMS Queue creations.
|
||||
*
|
||||
* @param queueCreator
|
||||
*/
|
||||
void setJMSQueueCreator(QueueCreator queueCreator);
|
||||
|
||||
/**
|
||||
* @see org.apache.activemq.artemis.core.server.ActiveMQServer#setJMSQueueCreator(QueueCreator)
|
||||
*/
|
||||
QueueCreator getJMSDestinationCreator();
|
||||
|
||||
/**
|
||||
* This is the queue deleter responsible for automatic JMS Queue deletions.
|
||||
*
|
||||
* @param queueDeleter
|
||||
*/
|
||||
void setJMSQueueDeleter(QueueDeleter queueDeleter);
|
||||
|
||||
/**
|
||||
* @see org.apache.activemq.artemis.core.server.ActiveMQServer#setJMSQueueDeleter(QueueDeleter)
|
||||
*/
|
||||
QueueDeleter getJMSQueueDeleter();
|
||||
|
||||
/**
|
||||
* Returns whether the initial replication synchronization process with the backup server is complete; applicable for
|
||||
* either the live or backup server.
|
||||
|
@ -369,7 +345,7 @@ public interface ActiveMQServer extends ActiveMQComponent {
|
|||
QueueQueryResult queueQuery(SimpleString name) throws Exception;
|
||||
|
||||
Queue deployQueue(SimpleString address,
|
||||
SimpleString resourceName,
|
||||
SimpleString queueName,
|
||||
SimpleString filterString,
|
||||
boolean durable,
|
||||
boolean temporary,
|
||||
|
|
|
@ -1,32 +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.core.server;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||
|
||||
public interface QueueCreator {
|
||||
|
||||
/**
|
||||
* You should return true if you even tried to create the queue and the queue was already there.
|
||||
* As the callers of this method will use that as an indicator that they should re-route the messages.
|
||||
* *
|
||||
*
|
||||
* @return True if a queue was created.
|
||||
*/
|
||||
boolean create(SimpleString address) throws Exception;
|
||||
}
|
|
@ -1,28 +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.core.server;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||
|
||||
public interface QueueDeleter {
|
||||
|
||||
/**
|
||||
* @return True if a queue was deleted.
|
||||
*/
|
||||
boolean delete(SimpleString queueName) throws Exception;
|
||||
}
|
|
@ -29,7 +29,7 @@ import org.apache.activemq.artemis.core.postoffice.PostOffice;
|
|||
*/
|
||||
public interface QueueFactory {
|
||||
|
||||
Queue createQueueWith(final QueueConfig config);
|
||||
Queue createQueueWith(final QueueConfig config) throws Exception;
|
||||
|
||||
/**
|
||||
* @deprecated Replaced by {@link #createQueueWith}
|
||||
|
|
|
@ -87,8 +87,6 @@ public interface ServerSession extends SecurityAuth {
|
|||
|
||||
void markTXFailed(Throwable e);
|
||||
|
||||
QueueCreator getQueueCreator();
|
||||
|
||||
List<Xid> xaGetInDoubtXids();
|
||||
|
||||
int xaGetTimeout();
|
||||
|
@ -194,7 +192,8 @@ public interface ServerSession extends SecurityAuth {
|
|||
boolean temporary,
|
||||
boolean durable,
|
||||
Integer maxConsumers,
|
||||
Boolean deleteOnNoConsumers) throws Exception;
|
||||
Boolean deleteOnNoConsumers,
|
||||
final Boolean autoCreated) throws Exception;
|
||||
|
||||
void createSharedQueue(SimpleString address,
|
||||
SimpleString name,
|
||||
|
|
|
@ -119,8 +119,6 @@ import org.apache.activemq.artemis.core.server.PostQueueCreationCallback;
|
|||
import org.apache.activemq.artemis.core.server.PostQueueDeletionCallback;
|
||||
import org.apache.activemq.artemis.core.server.Queue;
|
||||
import org.apache.activemq.artemis.core.server.QueueConfig;
|
||||
import org.apache.activemq.artemis.core.server.QueueCreator;
|
||||
import org.apache.activemq.artemis.core.server.QueueDeleter;
|
||||
import org.apache.activemq.artemis.core.server.QueueFactory;
|
||||
import org.apache.activemq.artemis.core.server.QueueQueryResult;
|
||||
import org.apache.activemq.artemis.core.server.SecuritySettingPlugin;
|
||||
|
@ -273,16 +271,6 @@ public class ActiveMQServerImpl implements ActiveMQServer {
|
|||
|
||||
private FileStoreMonitor fileStoreMonitor;
|
||||
|
||||
/**
|
||||
* This will be set by the JMS Queue Manager.
|
||||
*/
|
||||
private QueueCreator jmsQueueCreator;
|
||||
|
||||
/**
|
||||
* This will be set by the JMS Queue Manager.
|
||||
*/
|
||||
private QueueDeleter jmsQueueDeleter;
|
||||
|
||||
private final Map<String, ServerSession> sessions = new ConcurrentHashMap<>();
|
||||
|
||||
private final Semaphore activationLock = new Semaphore(1);
|
||||
|
@ -721,11 +709,7 @@ public class ActiveMQServerImpl implements ActiveMQServer {
|
|||
}
|
||||
}
|
||||
|
||||
if (autoCreateJmsTopics) {
|
||||
putAddressInfoIfAbsent(new AddressInfo(address));
|
||||
}
|
||||
|
||||
return new BindingQueryResult(getAddressInfo(address) != null, names, autoCreateJmsQueues, autoCreateJmsTopics);
|
||||
return new BindingQueryResult(!names.isEmpty(), names, autoCreateJmsQueues, autoCreateJmsTopics);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -793,26 +777,6 @@ public class ActiveMQServerImpl implements ActiveMQServer {
|
|||
stop(failoverOnServerShutdown, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueueCreator getJMSDestinationCreator() {
|
||||
return jmsQueueCreator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSQueueCreator(QueueCreator jmsQueueCreator) {
|
||||
this.jmsQueueCreator = jmsQueueCreator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueueDeleter getJMSQueueDeleter() {
|
||||
return jmsQueueDeleter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSQueueDeleter(QueueDeleter jmsQueueDeleter) {
|
||||
this.jmsQueueDeleter = jmsQueueDeleter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReplicaSync() {
|
||||
if (activation instanceof SharedNothingLiveActivation) {
|
||||
|
@ -1358,7 +1322,7 @@ public class ActiveMQServerImpl implements ActiveMQServer {
|
|||
SessionCallback callback,
|
||||
OperationContext context,
|
||||
boolean autoCreateJMSQueues) throws Exception {
|
||||
return new ServerSessionImpl(name, username, password, validatedUser, minLargeMessageSize, autoCommitSends, autoCommitAcks, preAcknowledge, configuration.isPersistDeliveryCountBeforeDelivery(), xa, connection, storageManager, postOffice, resourceManager, securityStore, managementService, this, configuration.getManagementAddress(), defaultAddress == null ? null : new SimpleString(defaultAddress), callback, context, autoCreateJMSQueues ? jmsQueueCreator : null, pagingManager);
|
||||
return new ServerSessionImpl(name, username, password, validatedUser, minLargeMessageSize, autoCommitSends, autoCommitAcks, preAcknowledge, configuration.isPersistDeliveryCountBeforeDelivery(), xa, connection, storageManager, postOffice, resourceManager, securityStore, managementService, this, configuration.getManagementAddress(), defaultAddress == null ? null : new SimpleString(defaultAddress), callback, context, pagingManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1616,17 +1580,17 @@ public class ActiveMQServerImpl implements ActiveMQServer {
|
|||
|
||||
@Override
|
||||
public Queue deployQueue(final SimpleString address,
|
||||
final SimpleString resourceName,
|
||||
final SimpleString queueName,
|
||||
final SimpleString filterString,
|
||||
final boolean durable,
|
||||
final boolean temporary,
|
||||
final boolean autoCreated) throws Exception {
|
||||
return deployQueue(address, resourceName, filterString, durable, temporary, autoCreated, null, null);
|
||||
return deployQueue(address, queueName, filterString, durable, temporary, autoCreated, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Queue deployQueue(final SimpleString address,
|
||||
final SimpleString resourceName,
|
||||
final SimpleString queueName,
|
||||
final SimpleString filterString,
|
||||
final boolean durable,
|
||||
final boolean temporary,
|
||||
|
@ -1635,9 +1599,9 @@ public class ActiveMQServerImpl implements ActiveMQServer {
|
|||
final Boolean deleteOnNoConsumers) throws Exception {
|
||||
|
||||
// TODO: fix logging here as this could be for a topic or queue
|
||||
ActiveMQServerLogger.LOGGER.deployQueue(resourceName);
|
||||
ActiveMQServerLogger.LOGGER.deployQueue(queueName);
|
||||
|
||||
return createQueue(address, resourceName, filterString, null, durable, temporary, true, false, autoCreated, maxConsumers, deleteOnNoConsumers);
|
||||
return createQueue(address, queueName, filterString, null, durable, temporary, true, false, autoCreated, maxConsumers, deleteOnNoConsumers);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2137,6 +2101,16 @@ public class ActiveMQServerImpl implements ActiveMQServer {
|
|||
// Deploy any predefined queues
|
||||
deployQueuesFromConfiguration();
|
||||
|
||||
registerPostQueueDeletionCallback(new PostQueueDeletionCallback() {
|
||||
// TODO delete auto-created addresses when queueCount == 0
|
||||
@Override
|
||||
public void callback(SimpleString address, SimpleString queueName) throws Exception {
|
||||
if (getAddressInfo(address).isAutoCreated() && postOffice.getBindingsForAddress(address).getBindings().size() == 0) {
|
||||
removeAddressInfo(address);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// We need to call this here, this gives any dependent server a chance to deploy its own addresses
|
||||
// this needs to be done before clustering is fully activated
|
||||
callActivateCallbacks();
|
||||
|
@ -2408,7 +2382,6 @@ public class ActiveMQServerImpl implements ActiveMQServer {
|
|||
final boolean autoCreated,
|
||||
final Integer maxConsumers,
|
||||
final Boolean deleteOnNoConsumers) throws Exception {
|
||||
|
||||
final QueueBinding binding = (QueueBinding) postOffice.getBinding(queueName);
|
||||
if (binding != null) {
|
||||
if (ignoreIfExists) {
|
||||
|
@ -2465,7 +2438,7 @@ public class ActiveMQServerImpl implements ActiveMQServer {
|
|||
if (transientQueue) {
|
||||
queue.setConsumersRefCount(new TransientQueueManagerImpl(this, queue.getName()));
|
||||
} else if (queue.isAutoCreated()) {
|
||||
queue.setConsumersRefCount(new AutoCreatedQueueManagerImpl(this.getJMSQueueDeleter(), queue.getName()));
|
||||
queue.setConsumersRefCount(new AutoCreatedQueueManagerImpl(this, queue.getName()));
|
||||
}
|
||||
|
||||
final QueueBinding localQueueBinding = new LocalQueueBinding(getAddressInfo(queue.getAddress()), queue, nodeManager.getNodeId());
|
||||
|
|
|
@ -29,6 +29,8 @@ public class AddressInfo {
|
|||
|
||||
private int defaultMaxQueueConsumers = ActiveMQDefaultConfiguration.getDefaultMaxQueueConsumers();
|
||||
|
||||
private boolean autoCreated = false;
|
||||
|
||||
public AddressInfo(SimpleString name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
@ -67,6 +69,15 @@ public class AddressInfo {
|
|||
return this;
|
||||
}
|
||||
|
||||
public boolean isAutoCreated() {
|
||||
return autoCreated;
|
||||
}
|
||||
|
||||
public AddressInfo setAutoCreated(boolean autoCreated) {
|
||||
this.autoCreated = autoCreated;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleString getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -78,6 +89,7 @@ public class AddressInfo {
|
|||
buff.append(", routingType=" + routingType);
|
||||
buff.append(", defaultMaxQueueConsumers=" + defaultMaxQueueConsumers);
|
||||
buff.append(", defaultDeleteOnNoConsumers=" + defaultDeleteOnNoConsumers);
|
||||
buff.append(", autoCreated=" + autoCreated);
|
||||
buff.append("]");
|
||||
return buff.toString();
|
||||
}
|
||||
|
|
|
@ -17,34 +17,48 @@
|
|||
package org.apache.activemq.artemis.core.server.impl;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
|
||||
import org.apache.activemq.artemis.core.server.AutoCreatedQueueManager;
|
||||
import org.apache.activemq.artemis.core.server.QueueDeleter;
|
||||
import org.apache.activemq.artemis.core.server.Queue;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.apache.activemq.artemis.utils.ReferenceCounterUtil;
|
||||
|
||||
public class AutoCreatedQueueManagerImpl implements AutoCreatedQueueManager {
|
||||
|
||||
private final SimpleString queueName;
|
||||
|
||||
private final QueueDeleter deleter;
|
||||
private final ActiveMQServer server;
|
||||
|
||||
private final Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (deleter != null) {
|
||||
deleter.delete(queueName);
|
||||
Queue queue = server.locateQueue(queueName);
|
||||
SimpleString address = queue.getAddress();
|
||||
AddressSettings settings = server.getAddressSettingsRepository().getMatch(address.toString());
|
||||
long consumerCount = queue.getConsumerCount();
|
||||
long messageCount = queue.getMessageCount();
|
||||
|
||||
// TODO make sure this is the right check
|
||||
if ((queue.isAutoCreated() || queue.isDeleteOnNoConsumers()) && queue.getMessageCount() == 0) {
|
||||
if (ActiveMQServerLogger.LOGGER.isDebugEnabled()) {
|
||||
ActiveMQServerLogger.LOGGER.debug("deleting auto-created queue \"" + queueName + ".\" consumerCount = " + consumerCount + "; messageCount = " + messageCount + "; getAutoDeleteJmsQueues = " + settings.getAutoDeleteJmsQueues());
|
||||
}
|
||||
|
||||
// TODO handle this exception better
|
||||
try {
|
||||
server.destroyQueue(queueName, null, true, false);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ActiveMQServerLogger.LOGGER.errorRemovingAutoCreatedQueue(e, queueName);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final ReferenceCounterUtil referenceCounterUtil = new ReferenceCounterUtil(runnable);
|
||||
|
||||
public AutoCreatedQueueManagerImpl(QueueDeleter deleter, SimpleString queueName) {
|
||||
this.deleter = deleter;
|
||||
public AutoCreatedQueueManagerImpl(ActiveMQServer server, SimpleString queueName) {
|
||||
this.server = server;
|
||||
this.queueName = queueName;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ public class DivertImpl implements Divert {
|
|||
copy = message;
|
||||
}
|
||||
|
||||
postOffice.route(copy, null, context.getTransaction(), false);
|
||||
postOffice.route(copy, context.getTransaction(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -151,9 +151,7 @@ public class PostOfficeJournalLoader implements JournalLoader {
|
|||
.deleteOnNoConsumers(queueBindingInfo.isDeleteOnNoConsumers())
|
||||
.maxConsumers(queueBindingInfo.getMaxConsumers());
|
||||
final Queue queue = queueFactory.createQueueWith(queueConfigBuilder.build());
|
||||
if (queue.isAutoCreated()) {
|
||||
queue.setConsumersRefCount(new AutoCreatedQueueManagerImpl(((PostOfficeImpl) postOffice).getServer().getJMSQueueDeleter(), queueBindingInfo.getQueueName()));
|
||||
}
|
||||
queue.setConsumersRefCount(new AutoCreatedQueueManagerImpl(((PostOfficeImpl)postOffice).getServer(), queueBindingInfo.getQueueName()));
|
||||
|
||||
if (queueBindingInfo.getQueueStatusEncodings() != null) {
|
||||
for (QueueStatusEncoding encoding : queueBindingInfo.getQueueStatusEncodings()) {
|
||||
|
|
|
@ -2326,7 +2326,7 @@ public class QueueImpl implements Queue {
|
|||
copyMessage.putBytesProperty(MessageImpl.HDR_ROUTE_TO_IDS, buffer.array());
|
||||
}
|
||||
|
||||
postOffice.route(copyMessage, null, tx, false, rejectDuplicate);
|
||||
postOffice.route(copyMessage, tx, false, rejectDuplicate);
|
||||
|
||||
acknowledge(tx, ref);
|
||||
}
|
||||
|
@ -2530,7 +2530,7 @@ public class QueueImpl implements Queue {
|
|||
|
||||
copyMessage.setAddress(address);
|
||||
|
||||
postOffice.route(copyMessage, null, tx, false, rejectDuplicate);
|
||||
postOffice.route(copyMessage, tx, false, rejectDuplicate);
|
||||
|
||||
acknowledge(tx, ref, reason);
|
||||
|
||||
|
|
|
@ -68,7 +68,6 @@ import org.apache.activemq.artemis.core.server.BindingQueryResult;
|
|||
import org.apache.activemq.artemis.core.server.LargeServerMessage;
|
||||
import org.apache.activemq.artemis.core.server.MessageReference;
|
||||
import org.apache.activemq.artemis.core.server.Queue;
|
||||
import org.apache.activemq.artemis.core.server.QueueCreator;
|
||||
import org.apache.activemq.artemis.core.server.QueueQueryResult;
|
||||
import org.apache.activemq.artemis.core.server.RoutingContext;
|
||||
import org.apache.activemq.artemis.core.server.ServerConsumer;
|
||||
|
@ -167,8 +166,6 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
|
|||
|
||||
private final OperationContext context;
|
||||
|
||||
private QueueCreator queueCreator;
|
||||
|
||||
// Session's usage should be by definition single threaded, hence it's not needed to use a concurrentHashMap here
|
||||
protected final Map<SimpleString, Pair<UUID, AtomicLong>> targetAddressInfos = new HashMap<>();
|
||||
|
||||
|
@ -203,7 +200,6 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
|
|||
final SimpleString defaultAddress,
|
||||
final SessionCallback callback,
|
||||
final OperationContext context,
|
||||
final QueueCreator queueCreator,
|
||||
final PagingManager pagingManager) throws Exception {
|
||||
this.username = username;
|
||||
|
||||
|
@ -251,8 +247,6 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
|
|||
remotingConnection.addFailureListener(this);
|
||||
this.context = context;
|
||||
|
||||
this.queueCreator = queueCreator;
|
||||
|
||||
if (!xa) {
|
||||
tx = newTransaction();
|
||||
}
|
||||
|
@ -390,11 +384,6 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueueCreator getQueueCreator() {
|
||||
return queueCreator;
|
||||
}
|
||||
|
||||
protected void securityCheck(SimpleString address, CheckType checkType, SecurityAuth auth) throws Exception {
|
||||
if (securityEnabled) {
|
||||
securityStore.check(address, checkType, auth);
|
||||
|
@ -500,7 +489,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
|
|||
final SimpleString filterString,
|
||||
final boolean temporary,
|
||||
final boolean durable) throws Exception {
|
||||
return createQueue(address, name, filterString, temporary, durable, null, null);
|
||||
return createQueue(address, name, filterString, temporary, durable, null, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -510,7 +499,8 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
|
|||
final boolean temporary,
|
||||
final boolean durable,
|
||||
final Integer maxConsumers,
|
||||
final Boolean deleteOnNoConsumers) throws Exception {
|
||||
final Boolean deleteOnNoConsumers,
|
||||
final Boolean autoCreated) throws Exception {
|
||||
if (durable) {
|
||||
// make sure the user has privileges to create this queue
|
||||
securityCheck(address, CheckType.CREATE_DURABLE_QUEUE, this);
|
||||
|
@ -520,7 +510,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
|
|||
|
||||
server.checkQueueCreationLimit(getUsername());
|
||||
|
||||
Queue queue = server.createQueue(address, name, filterString, SimpleString.toSimpleString(getUsername()), durable, temporary, maxConsumers, deleteOnNoConsumers);
|
||||
Queue queue = server.createQueue(address, name, filterString, SimpleString.toSimpleString(getUsername()), durable, temporary, autoCreated, maxConsumers, deleteOnNoConsumers);
|
||||
|
||||
if (temporary) {
|
||||
// Temporary queue in core simply means the queue will be deleted if
|
||||
|
@ -1485,7 +1475,6 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
|
|||
}
|
||||
|
||||
private void installJMSHooks() {
|
||||
this.queueCreator = server.getJMSDestinationCreator();
|
||||
}
|
||||
|
||||
private Map<SimpleString, Pair<UUID, AtomicLong>> cloneTargetAddresses() {
|
||||
|
@ -1605,11 +1594,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener {
|
|||
}
|
||||
|
||||
try {
|
||||
if (noAutoCreateQueue) {
|
||||
result = postOffice.route(msg, null, routingContext, direct);
|
||||
} else {
|
||||
result = postOffice.route(msg, queueCreator, routingContext, direct);
|
||||
}
|
||||
result = postOffice.route(msg, routingContext, direct);
|
||||
|
||||
Pair<UUID, AtomicLong> value = targetAddressInfos.get(msg.getAddress());
|
||||
|
||||
|
|
|
@ -464,7 +464,6 @@ public class ManagementServiceImpl implements ManagementService {
|
|||
public synchronized void registerInRegistry(final String resourceName, final Object managedResource) {
|
||||
unregisterFromRegistry(resourceName);
|
||||
|
||||
ActiveMQServerLogger.LOGGER.info("Registering: " + resourceName);
|
||||
registry.put(resourceName, managedResource);
|
||||
}
|
||||
|
||||
|
@ -653,7 +652,7 @@ public class ManagementServiceImpl implements ManagementService {
|
|||
notificationMessage.putStringProperty(new SimpleString("foobar"), new SimpleString(notification.getUID()));
|
||||
}
|
||||
|
||||
postOffice.route(notificationMessage, null, false);
|
||||
postOffice.route(notificationMessage, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,12 +46,14 @@ import org.apache.activemq.artemis.core.security.Role;
|
|||
import org.apache.activemq.artemis.core.server.JournalType;
|
||||
import org.apache.activemq.artemis.core.server.SecuritySettingPlugin;
|
||||
import org.apache.activemq.artemis.core.server.cluster.impl.MessageLoadBalancingType;
|
||||
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
|
||||
import org.apache.activemq.artemis.core.server.impl.LegacyLDAPSecuritySettingPlugin;
|
||||
import org.apache.activemq.artemis.core.settings.impl.SlowConsumerPolicy;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.apache.activemq.artemis.core.server.impl.AddressInfo.RoutingType.ANYCAST;
|
||||
import static org.apache.activemq.artemis.core.server.impl.AddressInfo.RoutingType.MULTICAST;
|
||||
|
||||
public class FileConfigurationTest extends ConfigurationImplTest {
|
||||
|
||||
private final String fullConfigurationName = "ConfigurationTest-full-config.xml";
|
||||
|
@ -376,7 +378,7 @@ public class FileConfigurationTest extends ConfigurationImplTest {
|
|||
// Addr 1
|
||||
CoreAddressConfiguration addressConfiguration = conf.getAddressConfigurations().get(0);
|
||||
assertEquals("addr1", addressConfiguration.getName());
|
||||
assertEquals(AddressInfo.RoutingType.ANYCAST, addressConfiguration.getRoutingType());
|
||||
assertEquals(ANYCAST, addressConfiguration.getRoutingType());
|
||||
assertEquals(2, addressConfiguration.getQueueConfigurations().size());
|
||||
|
||||
// Addr 1 Queue 1
|
||||
|
@ -402,7 +404,7 @@ public class FileConfigurationTest extends ConfigurationImplTest {
|
|||
// Addr 2
|
||||
addressConfiguration = conf.getAddressConfigurations().get(1);
|
||||
assertEquals("addr2", addressConfiguration.getName());
|
||||
assertEquals(AddressInfo.RoutingType.MULTICAST, addressConfiguration.getRoutingType());
|
||||
assertEquals(MULTICAST, addressConfiguration.getRoutingType());
|
||||
assertEquals(2, addressConfiguration.getQueueConfigurations().size());
|
||||
|
||||
// Addr 2 Queue 1
|
||||
|
|
|
@ -154,7 +154,7 @@ class IncomingVertxEventHandler implements ConnectorService {
|
|||
manualEncodeVertxMessageBody(msg.getBodyBuffer(), message.body(), type);
|
||||
|
||||
try {
|
||||
postOffice.route(msg, null, false);
|
||||
postOffice.route(msg, false);
|
||||
} catch (Exception e) {
|
||||
ActiveMQVertxLogger.LOGGER.error("failed to route msg " + msg, e);
|
||||
}
|
||||
|
|
|
@ -506,8 +506,9 @@ public abstract class BridgeTestBase extends ActiveMQTestBase {
|
|||
managementService = server1.getManagementService();
|
||||
}
|
||||
AddressControl topicControl = (AddressControl) managementService.getResource(ResourceNames.ADDRESS + topic.getTopicName());
|
||||
Assert.assertEquals(0, topicControl.getQueueNames().length);
|
||||
|
||||
if (topicControl != null) {
|
||||
Assert.assertEquals(0, topicControl.getQueueNames().length);
|
||||
}
|
||||
}
|
||||
|
||||
protected void removeAllMessages(final String queueName, final int index) throws Exception {
|
||||
|
|
|
@ -63,6 +63,7 @@ import javax.jms.TopicSession;
|
|||
import javax.jms.TopicSubscriber;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||
import org.apache.activemq.artemis.api.core.management.ResourceNames;
|
||||
import org.apache.activemq.artemis.core.postoffice.Bindings;
|
||||
import org.apache.activemq.artemis.core.remoting.CloseListener;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnector;
|
||||
|
@ -775,6 +776,7 @@ public class ProtonTest extends ProtonTestBase {
|
|||
Exception expectedException = null;
|
||||
try {
|
||||
session.createSender("AnAddressThatDoesNotExist");
|
||||
fail("Creating a sender here on an address that doesn't exist should fail");
|
||||
} catch (Exception e) {
|
||||
expectedException = e;
|
||||
}
|
||||
|
@ -896,7 +898,7 @@ public class ProtonTest extends ProtonTestBase {
|
|||
|
||||
//create request message for getQueueNames query
|
||||
AmqpMessage request = new AmqpMessage();
|
||||
request.setApplicationProperty("_AMQ_ResourceName", "core.server");
|
||||
request.setApplicationProperty("_AMQ_ResourceName", ResourceNames.BROKER);
|
||||
request.setApplicationProperty("_AMQ_OperationName", "getQueueNames");
|
||||
request.setReplyToAddress(destinationAddress);
|
||||
request.setText("[]");
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Set;
|
|||
import java.util.UUID;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||
import org.apache.activemq.artemis.api.core.management.ResourceNames;
|
||||
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
|
||||
import org.apache.activemq.artemis.core.security.Role;
|
||||
import org.apache.activemq.artemis.core.server.Queue;
|
||||
|
@ -144,7 +145,7 @@ public class AutoCreateJmsDestinationTest extends JMSTestBase {
|
|||
|
||||
connection.close();
|
||||
|
||||
assertNotNull(server.getManagementService().getResource("core.address.test"));
|
||||
assertNotNull(server.getManagementService().getResource(ResourceNames.ADDRESS + "test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -181,11 +182,11 @@ public class AutoCreateJmsDestinationTest extends JMSTestBase {
|
|||
connection.start();
|
||||
assertNotNull(consumer.receive(500));
|
||||
|
||||
assertNotNull(server.getManagementService().getResource("core.address." + topicName));
|
||||
assertNotNull(server.getManagementService().getResource(ResourceNames.ADDRESS + topicName));
|
||||
|
||||
connection.close();
|
||||
|
||||
assertNull(server.getManagementService().getResource("core.address." + topicName));
|
||||
assertNull(server.getManagementService().getResource(ResourceNames.ADDRESS + topicName));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -204,7 +205,7 @@ public class AutoCreateJmsDestinationTest extends JMSTestBase {
|
|||
|
||||
connection.close();
|
||||
|
||||
assertNotNull(server.getManagementService().getResource("core.address.test"));
|
||||
assertNotNull(server.getManagementService().getResource(ResourceNames.ADDRESS + "test"));
|
||||
|
||||
assertNotNull(server.locateQueue(SimpleString.toSimpleString("myClientID.myDurableSub")));
|
||||
}
|
||||
|
|
|
@ -513,7 +513,7 @@ public class HangConsumerTest extends ActiveMQTestBase {
|
|||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see SessionCallback#sendMessage(org.apache.activemq.artemis.core.server.ServerMessage, long, int)
|
||||
* @see SessionCallback#sendJmsMessage(org.apache.activemq.artemis.core.server.ServerMessage, long, int)
|
||||
*/
|
||||
@Override
|
||||
public int sendMessage(MessageReference ref, ServerMessage message, ServerConsumer consumer, int deliveryCount) {
|
||||
|
@ -592,7 +592,7 @@ public class HangConsumerTest extends ActiveMQTestBase {
|
|||
SessionCallback callback,
|
||||
OperationContext context,
|
||||
boolean autoCreateQueue) throws Exception {
|
||||
return new ServerSessionImpl(name, username, password, validatedUser, minLargeMessageSize, autoCommitSends, autoCommitAcks, preAcknowledge, getConfiguration().isPersistDeliveryCountBeforeDelivery(), xa, connection, getStorageManager(), getPostOffice(), getResourceManager(), getSecurityStore(), getManagementService(), this, getConfiguration().getManagementAddress(), defaultAddress == null ? null : new SimpleString(defaultAddress), new MyCallback(callback), context, null, getPagingManager());
|
||||
return new ServerSessionImpl(name, username, password, validatedUser, minLargeMessageSize, autoCommitSends, autoCommitAcks, preAcknowledge, getConfiguration().isPersistDeliveryCountBeforeDelivery(), xa, connection, getStorageManager(), getPostOffice(), getResourceManager(), getSecurityStore(), getManagementService(), this, getConfiguration().getManagementAddress(), defaultAddress == null ? null : new SimpleString(defaultAddress), new MyCallback(callback), context, getPagingManager());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryInternal
|
|||
import org.apache.activemq.artemis.core.client.impl.ClientSessionInternal;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.core.server.Queue;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
|
||||
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
|
||||
import org.apache.activemq.artemis.tests.util.CountDownSessionFailureListener;
|
||||
|
@ -228,6 +229,7 @@ public class SessionTest extends ActiveMQTestBase {
|
|||
|
||||
@Test
|
||||
public void testQueueQueryNoQ() throws Exception {
|
||||
server.getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateJmsQueues(false));
|
||||
cf = createSessionFactory(locator);
|
||||
ClientSession clientSession = cf.createSession(false, true, true);
|
||||
QueueQuery resp = clientSession.queueQuery(new SimpleString(queueName));
|
||||
|
|
|
@ -58,13 +58,15 @@ public class AutoCreateQueueClusterTest extends JMSClusteredTestBase {
|
|||
|
||||
Session session2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
MessageProducer prod1 = session1.createProducer(ActiveMQJMSClient.createQueue("myQueue"));
|
||||
// TODO the "jms." prefix is required here because the cluster connection only works for queues which start with "jms"
|
||||
MessageProducer prod1 = session1.createProducer(ActiveMQJMSClient.createQueue("jms.myQueue"));
|
||||
|
||||
prod1.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
|
||||
prod1.send(session1.createTextMessage("m1"));
|
||||
|
||||
MessageConsumer cons2 = session2.createConsumer(ActiveMQJMSClient.createQueue("myQueue"));
|
||||
// TODO the "jms." prefix is required here because the cluster connection only works for queues which start with "jms"
|
||||
MessageConsumer cons2 = session2.createConsumer(ActiveMQJMSClient.createQueue("jms.myQueue"));
|
||||
|
||||
TextMessage received = (TextMessage) cons2.receive(5000);
|
||||
|
||||
|
|
|
@ -25,9 +25,7 @@ import javax.jms.JMSException;
|
|||
import javax.jms.JMSProducer;
|
||||
import javax.jms.JMSRuntimeException;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.TransportConfiguration;
|
||||
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
|
||||
|
@ -36,26 +34,14 @@ import org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory;
|
|||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.apache.activemq.artemis.tests.util.JMSTestBase;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class NonExistentQueueTest extends JMSTestBase {
|
||||
|
||||
private JMSContext context;
|
||||
private final Random random = new Random();
|
||||
private Queue queue;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
context = createContext();
|
||||
queue = createQueue(JmsContextTest.class.getSimpleName() + "Queue1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendToNonExistentDestination() throws Exception {
|
||||
server.getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateJmsQueues(false));
|
||||
server.getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateJmsTopics(false));
|
||||
Destination destination = ActiveMQJMSClient.createTopic("DoesNotExist");
|
||||
TransportConfiguration transportConfiguration = new TransportConfiguration(InVMConnectorFactory.class.getName());
|
||||
ConnectionFactory localConnectionFactory = ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, transportConfiguration);
|
||||
|
|
|
@ -19,7 +19,6 @@ package org.apache.activemq.artemis.tests.integration.persistence;
|
|||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
@ -28,7 +27,6 @@ import java.io.ByteArrayInputStream;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.Message;
|
||||
|
@ -42,7 +40,6 @@ import org.apache.activemq.artemis.api.core.client.ClientSession;
|
|||
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
|
||||
import org.apache.activemq.artemis.api.core.client.ServerLocator;
|
||||
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
|
||||
import org.apache.activemq.artemis.api.jms.JMSFactoryType;
|
||||
import org.apache.activemq.artemis.cli.commands.tools.XmlDataExporter;
|
||||
import org.apache.activemq.artemis.cli.commands.tools.XmlDataImporter;
|
||||
import org.apache.activemq.artemis.core.persistence.impl.journal.BatchingIDGenerator;
|
||||
|
@ -51,7 +48,6 @@ import org.apache.activemq.artemis.core.persistence.impl.journal.LargeServerMess
|
|||
import org.apache.activemq.artemis.core.registry.JndiBindingRegistry;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.artemis.jms.server.JMSServerManager;
|
||||
import org.apache.activemq.artemis.jms.server.impl.JMSServerManagerImpl;
|
||||
import org.apache.activemq.artemis.tests.unit.util.InVMContext;
|
||||
|
@ -435,163 +431,6 @@ public class XmlImportExportTest extends ActiveMQTestBase {
|
|||
assertEquals(true, queueQuery.isDurable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJmsConnectionFactoryBinding() throws Exception {
|
||||
final String clientId = "myClientId";
|
||||
final long clientFailureCheckPeriod = 1;
|
||||
final long connectionTTl = 2;
|
||||
final long callTimeout = 3;
|
||||
final long callFailoverTimeout = 4;
|
||||
final boolean cacheLargeMessagesClient = true;
|
||||
final int minLargeMessageSize = 5;
|
||||
final boolean compressLargeMessages = true;
|
||||
final int consumerWindowSize = 6;
|
||||
final int consumerMaxRate = 7;
|
||||
final int confirmationWindowSize = 8;
|
||||
final int producerWindowSize = 9;
|
||||
final int producerMaxrate = 10;
|
||||
final boolean blockOnAcknowledge = true;
|
||||
final boolean blockOnDurableSend = false;
|
||||
final boolean blockOnNonDurableSend = true;
|
||||
final boolean autoGroup = true;
|
||||
final boolean preacknowledge = true;
|
||||
final String loadBalancingPolicyClassName = "myPolicy";
|
||||
final int transactionBatchSize = 11;
|
||||
final int dupsOKBatchSize = 12;
|
||||
final boolean useGlobalPools = true;
|
||||
final int scheduledThreadPoolMaxSize = 13;
|
||||
final int threadPoolMaxSize = 14;
|
||||
final long retryInterval = 15;
|
||||
final double retryIntervalMultiplier = 10.0;
|
||||
final long maxRetryInterval = 16;
|
||||
final int reconnectAttempts = 17;
|
||||
final boolean failoverOnInitialConnection = true;
|
||||
final String groupId = "myGroupId";
|
||||
final String name = "myFirstConnectionFactoryName";
|
||||
final String jndi_binding1 = name + "Binding1";
|
||||
final String jndi_binding2 = name + "Binding2";
|
||||
final JMSFactoryType type = JMSFactoryType.CF;
|
||||
final boolean ha = true;
|
||||
final List<String> connectors = Arrays.asList("in-vm1", "in-vm2");
|
||||
|
||||
ClientSession session = basicSetUp();
|
||||
|
||||
jmsServer.createConnectionFactory(name, ha, type, connectors, clientId, clientFailureCheckPeriod, connectionTTl, callTimeout, callFailoverTimeout, cacheLargeMessagesClient, minLargeMessageSize, compressLargeMessages, consumerWindowSize, consumerMaxRate, confirmationWindowSize, producerWindowSize, producerMaxrate, blockOnAcknowledge, blockOnDurableSend, blockOnNonDurableSend, autoGroup, preacknowledge, loadBalancingPolicyClassName, transactionBatchSize, dupsOKBatchSize, useGlobalPools, scheduledThreadPoolMaxSize, threadPoolMaxSize, retryInterval, retryIntervalMultiplier, maxRetryInterval, reconnectAttempts, failoverOnInitialConnection, groupId, jndi_binding1, jndi_binding2);
|
||||
|
||||
jmsServer.createConnectionFactory("mySecondConnectionFactoryName", false, JMSFactoryType.CF, Arrays.asList("in-vm1", "in-vm2"), "mySecondConnectionFactoryName1", "mySecondConnectionFactoryName2");
|
||||
|
||||
session.close();
|
||||
locator.close();
|
||||
server.stop();
|
||||
|
||||
ByteArrayOutputStream xmlOutputStream = new ByteArrayOutputStream();
|
||||
XmlDataExporter xmlDataExporter = new XmlDataExporter();
|
||||
xmlDataExporter.process(xmlOutputStream, server.getConfiguration().getBindingsLocation().getAbsolutePath(), server.getConfiguration().getJournalLocation().getAbsolutePath(), server.getConfiguration().getPagingLocation().getAbsolutePath(), server.getConfiguration().getLargeMessagesLocation().getAbsolutePath());
|
||||
System.out.print(new String(xmlOutputStream.toByteArray()));
|
||||
|
||||
clearDataRecreateServerDirs();
|
||||
server.start();
|
||||
checkForLongs();
|
||||
locator = createInVMNonHALocator();
|
||||
factory = createSessionFactory(locator);
|
||||
session = factory.createSession(false, true, true);
|
||||
|
||||
ByteArrayInputStream xmlInputStream = new ByteArrayInputStream(xmlOutputStream.toByteArray());
|
||||
XmlDataImporter xmlDataImporter = new XmlDataImporter();
|
||||
xmlDataImporter.process(xmlInputStream, session);
|
||||
|
||||
ConnectionFactory cf1 = (ConnectionFactory) namingContext.lookup(jndi_binding1);
|
||||
assertNotNull(cf1);
|
||||
ActiveMQConnectionFactory hcf1 = (ActiveMQConnectionFactory) cf1;
|
||||
assertEquals(ha, hcf1.isHA());
|
||||
assertEquals(type.intValue(), hcf1.getFactoryType());
|
||||
assertEquals(clientId, hcf1.getClientID());
|
||||
assertEquals(clientFailureCheckPeriod, hcf1.getClientFailureCheckPeriod());
|
||||
assertEquals(connectionTTl, hcf1.getConnectionTTL());
|
||||
assertEquals(callTimeout, hcf1.getCallTimeout());
|
||||
// Assert.assertEquals(callFailoverTimeout, hcf1.getCallFailoverTimeout()); // this value isn't currently persisted by org.apache.activemq.artemis.jms.server.config.impl.ConnectionFactoryConfigurationImpl.encode()
|
||||
// Assert.assertEquals(cacheLargeMessagesClient, hcf1.isCacheLargeMessagesClient()); // this value isn't currently supported by org.apache.activemq.artemis.api.jms.management.JMSServerControl.createConnectionFactory(java.lang.String, boolean, boolean, int, java.lang.String, java.lang.String, java.lang.String, long, long, long, long, int, boolean, int, int, int, int, int, boolean, boolean, boolean, boolean, boolean, java.lang.String, int, int, boolean, int, int, long, double, long, int, boolean, java.lang.String)
|
||||
assertEquals(minLargeMessageSize, hcf1.getMinLargeMessageSize());
|
||||
// Assert.assertEquals(compressLargeMessages, hcf1.isCompressLargeMessage()); // this value isn't currently handled properly by org.apache.activemq.artemis.jms.server.impl.JMSServerManagerImpl.createConnectionFactory(java.lang.String, boolean, org.apache.activemq.artemis.api.jms.JMSFactoryType, java.util.List<java.lang.String>, java.lang.String, long, long, long, long, boolean, int, boolean, int, int, int, int, int, boolean, boolean, boolean, boolean, boolean, java.lang.String, int, int, boolean, int, int, long, double, long, int, boolean, java.lang.String, java.lang.String...)()
|
||||
assertEquals(consumerWindowSize, hcf1.getConsumerWindowSize());
|
||||
assertEquals(consumerMaxRate, hcf1.getConsumerMaxRate());
|
||||
assertEquals(confirmationWindowSize, hcf1.getConfirmationWindowSize());
|
||||
assertEquals(producerWindowSize, hcf1.getProducerWindowSize());
|
||||
assertEquals(producerMaxrate, hcf1.getProducerMaxRate());
|
||||
assertEquals(blockOnAcknowledge, hcf1.isBlockOnAcknowledge());
|
||||
assertEquals(blockOnDurableSend, hcf1.isBlockOnDurableSend());
|
||||
assertEquals(blockOnNonDurableSend, hcf1.isBlockOnNonDurableSend());
|
||||
assertEquals(autoGroup, hcf1.isAutoGroup());
|
||||
assertEquals(preacknowledge, hcf1.isPreAcknowledge());
|
||||
assertEquals(loadBalancingPolicyClassName, hcf1.getConnectionLoadBalancingPolicyClassName());
|
||||
assertEquals(transactionBatchSize, hcf1.getTransactionBatchSize());
|
||||
assertEquals(dupsOKBatchSize, hcf1.getDupsOKBatchSize());
|
||||
assertEquals(useGlobalPools, hcf1.isUseGlobalPools());
|
||||
assertEquals(scheduledThreadPoolMaxSize, hcf1.getScheduledThreadPoolMaxSize());
|
||||
assertEquals(threadPoolMaxSize, hcf1.getThreadPoolMaxSize());
|
||||
assertEquals(retryInterval, hcf1.getRetryInterval());
|
||||
assertEquals(retryIntervalMultiplier, hcf1.getRetryIntervalMultiplier(), 0);
|
||||
assertEquals(maxRetryInterval, hcf1.getMaxRetryInterval());
|
||||
assertEquals(reconnectAttempts, hcf1.getReconnectAttempts());
|
||||
assertEquals(failoverOnInitialConnection, hcf1.isFailoverOnInitialConnection());
|
||||
assertEquals(groupId, hcf1.getGroupID());
|
||||
|
||||
assertNotNull(namingContext.lookup(jndi_binding2));
|
||||
assertNotNull(namingContext.lookup("mySecondConnectionFactoryName1"));
|
||||
assertNotNull(namingContext.lookup("mySecondConnectionFactoryName2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJmsDestination() throws Exception {
|
||||
ClientSession session = basicSetUp();
|
||||
|
||||
jmsServer.createQueue(true, "myQueue", null, true, "myQueueJndiBinding1", "myQueueJndiBinding2");
|
||||
jmsServer.createTopic(true, "myTopic", "myTopicJndiBinding1", "myTopicJndiBinding2");
|
||||
|
||||
session.close();
|
||||
locator.close();
|
||||
server.stop();
|
||||
|
||||
ByteArrayOutputStream xmlOutputStream = new ByteArrayOutputStream();
|
||||
XmlDataExporter xmlDataExporter = new XmlDataExporter();
|
||||
xmlDataExporter.process(xmlOutputStream, server.getConfiguration().getBindingsDirectory(), server.getConfiguration().getJournalDirectory(), server.getConfiguration().getPagingDirectory(), server.getConfiguration().getLargeMessagesDirectory());
|
||||
System.out.print(new String(xmlOutputStream.toByteArray()));
|
||||
|
||||
clearDataRecreateServerDirs();
|
||||
server.start();
|
||||
checkForLongs();
|
||||
locator = createInVMNonHALocator();
|
||||
factory = createSessionFactory(locator);
|
||||
session = factory.createSession(false, true, true);
|
||||
|
||||
ByteArrayInputStream xmlInputStream = new ByteArrayInputStream(xmlOutputStream.toByteArray());
|
||||
XmlDataImporter xmlDataImporter = new XmlDataImporter();
|
||||
xmlDataImporter.process(xmlInputStream, session);
|
||||
|
||||
assertNotNull(namingContext.lookup("myQueueJndiBinding1"));
|
||||
assertNotNull(namingContext.lookup("myQueueJndiBinding2"));
|
||||
assertNotNull(namingContext.lookup("myTopicJndiBinding1"));
|
||||
assertNotNull(namingContext.lookup("myTopicJndiBinding2"));
|
||||
|
||||
jmsServer.createConnectionFactory("test-cf", false, JMSFactoryType.CF, Arrays.asList("in-vm1"), "test-cf");
|
||||
|
||||
ConnectionFactory cf = (ConnectionFactory) namingContext.lookup("test-cf");
|
||||
Connection connection = cf.createConnection();
|
||||
Session jmsSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = jmsSession.createProducer((Destination) namingContext.lookup("myQueueJndiBinding1"));
|
||||
producer.send(jmsSession.createTextMessage());
|
||||
MessageConsumer consumer = jmsSession.createConsumer((Destination) namingContext.lookup("myQueueJndiBinding2"));
|
||||
connection.start();
|
||||
assertNotNull(consumer.receive(3000));
|
||||
|
||||
consumer = jmsSession.createConsumer((Destination) namingContext.lookup("myTopicJndiBinding1"));
|
||||
producer = jmsSession.createProducer((Destination) namingContext.lookup("myTopicJndiBinding2"));
|
||||
producer.send(jmsSession.createTextMessage());
|
||||
assertNotNull(consumer.receive(3000));
|
||||
|
||||
connection.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLargeMessage() throws Exception {
|
||||
server = createServer(true);
|
||||
|
|
|
@ -1,136 +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.tests.integration.stomp;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ConcurrentStompTest extends StompTestBase {
|
||||
|
||||
private Socket stompSocket_2;
|
||||
|
||||
private ByteArrayOutputStream inputBuffer_2;
|
||||
|
||||
/**
|
||||
* Send messages on 1 socket and receives them concurrently on another socket.
|
||||
*/
|
||||
@Test
|
||||
public void testSendManyMessages() throws Exception {
|
||||
try {
|
||||
String connect = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n\n" + Stomp.NULL;
|
||||
|
||||
sendFrame(connect);
|
||||
String connected = receiveFrame(10000);
|
||||
Assert.assertTrue(connected.startsWith("CONNECTED"));
|
||||
|
||||
stompSocket_2 = createSocket();
|
||||
inputBuffer_2 = new ByteArrayOutputStream();
|
||||
|
||||
sendFrame(stompSocket_2, connect);
|
||||
connected = receiveFrame(stompSocket_2, inputBuffer_2, 10000);
|
||||
Assert.assertTrue(connected.startsWith("CONNECTED"));
|
||||
|
||||
final int count = 1000;
|
||||
final CountDownLatch latch = new CountDownLatch(count);
|
||||
|
||||
String subscribe = "SUBSCRIBE\n" +
|
||||
"destination:" + getQueuePrefix() + getQueueName() + "\n" +
|
||||
"ack:auto\n\n" +
|
||||
Stomp.NULL;
|
||||
sendFrame(stompSocket_2, subscribe);
|
||||
Thread.sleep(2000);
|
||||
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
int i = 0;
|
||||
while (true) {
|
||||
try {
|
||||
String frame = receiveFrame(stompSocket_2, inputBuffer_2, 10000);
|
||||
Assert.assertTrue(frame.startsWith("MESSAGE"));
|
||||
Assert.assertTrue(frame.indexOf("destination:") > 0);
|
||||
System.out.println("<<< " + i++);
|
||||
latch.countDown();
|
||||
} catch (Exception e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
|
||||
String send = "SEND\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n";
|
||||
for (int i = 1; i <= count; i++) {
|
||||
// Thread.sleep(1);
|
||||
System.out.println(">>> " + i);
|
||||
sendFrame(send + "count:" + i + "\n\n" + Stomp.NULL);
|
||||
}
|
||||
|
||||
assertTrue(latch.await(60, TimeUnit.SECONDS));
|
||||
|
||||
} finally {
|
||||
stompSocket_2.close();
|
||||
inputBuffer_2.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Implementation methods
|
||||
// -------------------------------------------------------------------------
|
||||
public void sendFrame(Socket socket, String data) throws Exception {
|
||||
byte[] bytes = data.getBytes(StandardCharsets.UTF_8);
|
||||
OutputStream outputStream = socket.getOutputStream();
|
||||
for (byte b : bytes) {
|
||||
outputStream.write(b);
|
||||
}
|
||||
outputStream.flush();
|
||||
}
|
||||
|
||||
public String receiveFrame(Socket socket, ByteArrayOutputStream input, long timeOut) throws Exception {
|
||||
socket.setSoTimeout((int) timeOut);
|
||||
InputStream is = socket.getInputStream();
|
||||
int c = 0;
|
||||
for (;;) {
|
||||
c = is.read();
|
||||
if (c < 0) {
|
||||
throw new IOException("socket closed.");
|
||||
} else if (c == 0) {
|
||||
c = is.read();
|
||||
if (c != '\n') {
|
||||
byte[] ba = input.toByteArray();
|
||||
System.out.println(new String(ba, StandardCharsets.UTF_8));
|
||||
}
|
||||
Assert.assertEquals("Expecting stomp frame to terminate with \0\n", c, '\n');
|
||||
byte[] ba = input.toByteArray();
|
||||
input.reset();
|
||||
return new String(ba, StandardCharsets.UTF_8);
|
||||
} else {
|
||||
input.write(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,848 +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.tests.integration.stomp;
|
||||
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.QueueBrowser;
|
||||
import javax.jms.TextMessage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.Interceptor;
|
||||
import org.apache.activemq.artemis.api.core.TransportConfiguration;
|
||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.protocol.core.Packet;
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.StompFrame;
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.StompFrameInterceptor;
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.StompProtocolManagerFactory;
|
||||
import org.apache.activemq.artemis.core.registry.JndiBindingRegistry;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptorFactory;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServers;
|
||||
import org.apache.activemq.artemis.jms.server.JMSServerManager;
|
||||
import org.apache.activemq.artemis.jms.server.config.JMSConfiguration;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.JMSConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.JMSQueueConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.TopicConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.impl.JMSServerManagerImpl;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
|
||||
import org.apache.activemq.artemis.tests.integration.largemessage.LargeMessageTestBase;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnection;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnectionFactory;
|
||||
import org.apache.activemq.artemis.tests.unit.util.InVMNamingContext;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ExtraStompTest extends StompTestBase {
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
autoCreateServer = false;
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionTTL() throws Exception {
|
||||
try {
|
||||
server = createServerWithTTL("2000");
|
||||
server.start();
|
||||
|
||||
setUpAfterServer();
|
||||
|
||||
String connect_frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n" + "request-id: 1\n" + "\n" + Stomp.NULL;
|
||||
sendFrame(connect_frame);
|
||||
|
||||
String f = receiveFrame(10000);
|
||||
Assert.assertTrue(f.startsWith("CONNECTED"));
|
||||
Assert.assertTrue(f.indexOf("response-id:1") >= 0);
|
||||
|
||||
String frame = "SEND\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n\n" + "Hello World 1" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
|
||||
assertChannelClosed();
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
|
||||
TextMessage message = (TextMessage) consumer.receiveNoWait();
|
||||
Assert.assertNotNull(message);
|
||||
|
||||
message = (TextMessage) consumer.receiveNoWait();
|
||||
Assert.assertNull(message);
|
||||
} finally {
|
||||
cleanUp();
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableMessageID() throws Exception {
|
||||
enableMessageIDTest(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisableMessageID() throws Exception {
|
||||
enableMessageIDTest(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultEnableMessageID() throws Exception {
|
||||
enableMessageIDTest(null);
|
||||
}
|
||||
|
||||
//stomp sender -> large -> stomp receiver
|
||||
@Test
|
||||
public void testSendReceiveLargePersistentMessages() throws Exception {
|
||||
try {
|
||||
server = createPersistentServerWithStompMinLargeSize(2048);
|
||||
server.start();
|
||||
|
||||
setUpAfterServer();
|
||||
|
||||
String frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
frame = receiveFrame(10000);
|
||||
|
||||
Assert.assertTrue(frame.startsWith("CONNECTED"));
|
||||
int count = 10;
|
||||
int szBody = 1024 * 1024;
|
||||
char[] contents = new char[szBody];
|
||||
for (int i = 0; i < szBody; i++) {
|
||||
contents[i] = 'A';
|
||||
}
|
||||
String body = new String(contents);
|
||||
|
||||
frame = "SEND\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n" + "persistent:true\n" + "\n\n" + body + Stomp.NULL;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
sendFrame(frame);
|
||||
}
|
||||
|
||||
frame = "SUBSCRIBE\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n" + "ack:auto\n\nfff" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
frame = receiveFrame(60000);
|
||||
Assert.assertNotNull(frame);
|
||||
System.out.println("part of frame: " + frame.substring(0, 200));
|
||||
Assert.assertTrue(frame.startsWith("MESSAGE"));
|
||||
Assert.assertTrue(frame.indexOf("destination:") > 0);
|
||||
int index = frame.indexOf("AAAA");
|
||||
assertEquals(szBody, (frame.length() - index));
|
||||
}
|
||||
|
||||
// remove suscription
|
||||
frame = "UNSUBSCRIBE\n" + "destination:" +
|
||||
getQueuePrefix() +
|
||||
getQueueName() +
|
||||
"\n" +
|
||||
"receipt:567\n" +
|
||||
"\n\n" +
|
||||
Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
waitForReceipt();
|
||||
|
||||
frame = "DISCONNECT\n" + "\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw ex;
|
||||
} finally {
|
||||
cleanUp();
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
//core sender -> large -> stomp receiver
|
||||
@Test
|
||||
public void testReceiveLargePersistentMessagesFromCore() throws Exception {
|
||||
try {
|
||||
server = createPersistentServerWithStompMinLargeSize(2048);
|
||||
server.start();
|
||||
|
||||
setUpAfterServer();
|
||||
|
||||
int msgSize = 3 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE;
|
||||
char[] contents = new char[msgSize];
|
||||
for (int i = 0; i < msgSize; i++) {
|
||||
contents[i] = 'B';
|
||||
}
|
||||
String msg = new String(contents);
|
||||
|
||||
int count = 10;
|
||||
for (int i = 0; i < count; i++) {
|
||||
this.sendMessage(msg);
|
||||
}
|
||||
|
||||
String frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
frame = receiveFrame(10000);
|
||||
|
||||
Assert.assertTrue(frame.startsWith("CONNECTED"));
|
||||
|
||||
frame = "SUBSCRIBE\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n" + "ack:auto\n\nfff" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
frame = receiveFrame(60000);
|
||||
Assert.assertNotNull(frame);
|
||||
System.out.println("part of frame: " + frame.substring(0, 250));
|
||||
Assert.assertTrue(frame.startsWith("MESSAGE"));
|
||||
Assert.assertTrue(frame.indexOf("destination:") > 0);
|
||||
int index = frame.indexOf("BBBB");
|
||||
assertEquals(msgSize, (frame.length() - index));
|
||||
}
|
||||
|
||||
// remove suscription
|
||||
frame = "UNSUBSCRIBE\n" + "destination:" +
|
||||
getQueuePrefix() +
|
||||
getQueueName() +
|
||||
"\n" +
|
||||
"receipt:567\n" +
|
||||
"\n\n" +
|
||||
Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
waitForReceipt();
|
||||
|
||||
frame = "DISCONNECT\n" + "\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw ex;
|
||||
} finally {
|
||||
cleanUp();
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
//stomp v12 sender -> large -> stomp v12 receiver
|
||||
@Test
|
||||
public void testSendReceiveLargePersistentMessagesV12() throws Exception {
|
||||
try {
|
||||
server = createPersistentServerWithStompMinLargeSize(2048);
|
||||
server.start();
|
||||
|
||||
setUpAfterServer();
|
||||
|
||||
StompClientConnection connV12 = StompClientConnectionFactory.createClientConnection("1.2", "localhost", port);
|
||||
connV12.connect(defUser, defPass);
|
||||
|
||||
int count = 10;
|
||||
int szBody = 1024 * 1024;
|
||||
char[] contents = new char[szBody];
|
||||
for (int i = 0; i < szBody; i++) {
|
||||
contents[i] = 'A';
|
||||
}
|
||||
String body = new String(contents);
|
||||
|
||||
ClientStompFrame frame = connV12.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("persistent", "true");
|
||||
frame.setBody(body);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
connV12.sendFrame(frame);
|
||||
}
|
||||
|
||||
ClientStompFrame subFrame = connV12.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
|
||||
connV12.sendFrame(subFrame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame receiveFrame = connV12.receiveFrame(30000);
|
||||
|
||||
Assert.assertNotNull(receiveFrame);
|
||||
System.out.println("part of frame: " + receiveFrame.getBody().substring(0, 20));
|
||||
Assert.assertTrue(receiveFrame.getCommand().equals("MESSAGE"));
|
||||
Assert.assertEquals(receiveFrame.getHeader("destination"), getQueuePrefix() + getQueueName());
|
||||
assertEquals(szBody, receiveFrame.getBody().length());
|
||||
}
|
||||
|
||||
// remove susbcription
|
||||
ClientStompFrame unsubFrame = connV12.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV12.sendFrame(unsubFrame);
|
||||
|
||||
connV12.disconnect();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw ex;
|
||||
} finally {
|
||||
cleanUp();
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
//core sender -> large -> stomp v12 receiver
|
||||
@Test
|
||||
public void testReceiveLargePersistentMessagesFromCoreV12() throws Exception {
|
||||
try {
|
||||
server = createPersistentServerWithStompMinLargeSize(2048);
|
||||
server.start();
|
||||
|
||||
setUpAfterServer();
|
||||
|
||||
int msgSize = 3 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE;
|
||||
char[] contents = new char[msgSize];
|
||||
for (int i = 0; i < msgSize; i++) {
|
||||
contents[i] = 'B';
|
||||
}
|
||||
String msg = new String(contents);
|
||||
|
||||
int count = 10;
|
||||
for (int i = 0; i < count; i++) {
|
||||
this.sendMessage(msg);
|
||||
}
|
||||
|
||||
StompClientConnection connV12 = StompClientConnectionFactory.createClientConnection("1.2", "localhost", port);
|
||||
connV12.connect(defUser, defPass);
|
||||
|
||||
ClientStompFrame subFrame = connV12.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
|
||||
connV12.sendFrame(subFrame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame receiveFrame = connV12.receiveFrame(30000);
|
||||
|
||||
Assert.assertNotNull(receiveFrame);
|
||||
System.out.println("part of frame: " + receiveFrame.getBody().substring(0, 20));
|
||||
Assert.assertTrue(receiveFrame.getCommand().equals("MESSAGE"));
|
||||
Assert.assertEquals(receiveFrame.getHeader("destination"), getQueuePrefix() + getQueueName());
|
||||
assertEquals(msgSize, receiveFrame.getBody().length());
|
||||
}
|
||||
|
||||
// remove susbcription
|
||||
ClientStompFrame unsubFrame = connV12.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV12.sendFrame(unsubFrame);
|
||||
|
||||
connV12.disconnect();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw ex;
|
||||
} finally {
|
||||
cleanUp();
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
//core sender -> large (compressed regular) -> stomp v10 receiver
|
||||
@Test
|
||||
public void testReceiveLargeCompressedToRegularPersistentMessagesFromCore() throws Exception {
|
||||
try {
|
||||
server = createPersistentServerWithStompMinLargeSize(2048);
|
||||
server.start();
|
||||
|
||||
setUpAfterServer(true);
|
||||
|
||||
LargeMessageTestBase.TestLargeMessageInputStream input = new LargeMessageTestBase.TestLargeMessageInputStream(ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, true);
|
||||
LargeMessageTestBase.adjustLargeCompression(true, input, ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
|
||||
|
||||
char[] contents = input.toArray();
|
||||
String msg = new String(contents);
|
||||
|
||||
String leadingPart = msg.substring(0, 100);
|
||||
|
||||
int count = 10;
|
||||
for (int i = 0; i < count; i++) {
|
||||
this.sendMessage(msg);
|
||||
}
|
||||
|
||||
String frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
frame = receiveFrame(10000);
|
||||
|
||||
Assert.assertTrue(frame.startsWith("CONNECTED"));
|
||||
|
||||
frame = "SUBSCRIBE\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n" + "ack:auto\n\nfff" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
frame = receiveFrame(60000);
|
||||
Assert.assertNotNull(frame);
|
||||
System.out.println("part of frame: " + frame.substring(0, 250));
|
||||
Assert.assertTrue(frame.startsWith("MESSAGE"));
|
||||
Assert.assertTrue(frame.indexOf("destination:") > 0);
|
||||
int index = frame.indexOf(leadingPart);
|
||||
assertEquals(msg.length(), (frame.length() - index));
|
||||
}
|
||||
|
||||
// remove suscription
|
||||
frame = "UNSUBSCRIBE\n" + "destination:" +
|
||||
getQueuePrefix() +
|
||||
getQueueName() +
|
||||
"\n" +
|
||||
"receipt:567\n" +
|
||||
"\n\n" +
|
||||
Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
waitForReceipt();
|
||||
|
||||
frame = "DISCONNECT\n" + "\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw ex;
|
||||
} finally {
|
||||
cleanUp();
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
//core sender -> large (compressed regular) -> stomp v12 receiver
|
||||
@Test
|
||||
public void testReceiveLargeCompressedToRegularPersistentMessagesFromCoreV12() throws Exception {
|
||||
try {
|
||||
server = createPersistentServerWithStompMinLargeSize(2048);
|
||||
server.start();
|
||||
|
||||
setUpAfterServer(true);
|
||||
|
||||
LargeMessageTestBase.TestLargeMessageInputStream input = new LargeMessageTestBase.TestLargeMessageInputStream(ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, true);
|
||||
LargeMessageTestBase.adjustLargeCompression(true, input, ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
|
||||
|
||||
char[] contents = input.toArray();
|
||||
String msg = new String(contents);
|
||||
|
||||
int count = 10;
|
||||
for (int i = 0; i < count; i++) {
|
||||
this.sendMessage(msg);
|
||||
}
|
||||
|
||||
StompClientConnection connV12 = StompClientConnectionFactory.createClientConnection("1.2", "localhost", port);
|
||||
connV12.connect(defUser, defPass);
|
||||
|
||||
ClientStompFrame subFrame = connV12.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
|
||||
connV12.sendFrame(subFrame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame receiveFrame = connV12.receiveFrame(30000);
|
||||
|
||||
Assert.assertNotNull(receiveFrame);
|
||||
System.out.println("part of frame: " + receiveFrame.getBody().substring(0, 20));
|
||||
Assert.assertTrue(receiveFrame.getCommand().equals("MESSAGE"));
|
||||
Assert.assertEquals(receiveFrame.getHeader("destination"), getQueuePrefix() + getQueueName());
|
||||
assertEquals(contents.length, receiveFrame.getBody().length());
|
||||
}
|
||||
|
||||
// remove susbcription
|
||||
ClientStompFrame unsubFrame = connV12.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV12.sendFrame(unsubFrame);
|
||||
|
||||
connV12.disconnect();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw ex;
|
||||
} finally {
|
||||
cleanUp();
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
//core sender -> large (compressed large) -> stomp v12 receiver
|
||||
@Test
|
||||
public void testReceiveLargeCompressedToLargePersistentMessagesFromCoreV12() throws Exception {
|
||||
try {
|
||||
server = createPersistentServerWithStompMinLargeSize(2048);
|
||||
server.start();
|
||||
|
||||
setUpAfterServer(true);
|
||||
|
||||
LargeMessageTestBase.TestLargeMessageInputStream input = new LargeMessageTestBase.TestLargeMessageInputStream(ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, true);
|
||||
input.setSize(10 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
|
||||
LargeMessageTestBase.adjustLargeCompression(false, input, 10 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
|
||||
|
||||
char[] contents = input.toArray();
|
||||
String msg = new String(contents);
|
||||
|
||||
int count = 10;
|
||||
for (int i = 0; i < count; i++) {
|
||||
this.sendMessage(msg);
|
||||
}
|
||||
|
||||
StompClientConnection connV12 = StompClientConnectionFactory.createClientConnection("1.2", "localhost", port);
|
||||
connV12.connect(defUser, defPass);
|
||||
|
||||
ClientStompFrame subFrame = connV12.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
|
||||
connV12.sendFrame(subFrame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame receiveFrame = connV12.receiveFrame(30000);
|
||||
|
||||
Assert.assertNotNull(receiveFrame);
|
||||
System.out.println("part of frame: " + receiveFrame.getBody().substring(0, 20));
|
||||
Assert.assertTrue(receiveFrame.getCommand().equals("MESSAGE"));
|
||||
Assert.assertEquals(receiveFrame.getHeader("destination"), getQueuePrefix() + getQueueName());
|
||||
assertEquals(contents.length, receiveFrame.getBody().length());
|
||||
}
|
||||
|
||||
// remove susbcription
|
||||
ClientStompFrame unsubFrame = connV12.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV12.sendFrame(unsubFrame);
|
||||
|
||||
connV12.disconnect();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw ex;
|
||||
} finally {
|
||||
cleanUp();
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
//core sender -> large (compressed large) -> stomp v10 receiver
|
||||
@Test
|
||||
public void testReceiveLargeCompressedToLargePersistentMessagesFromCore() throws Exception {
|
||||
try {
|
||||
server = createPersistentServerWithStompMinLargeSize(2048);
|
||||
server.start();
|
||||
|
||||
setUpAfterServer(true);
|
||||
|
||||
LargeMessageTestBase.TestLargeMessageInputStream input = new LargeMessageTestBase.TestLargeMessageInputStream(ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, true);
|
||||
input.setSize(10 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
|
||||
LargeMessageTestBase.adjustLargeCompression(false, input, 10 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
|
||||
|
||||
char[] contents = input.toArray();
|
||||
String msg = new String(contents);
|
||||
|
||||
String leadingPart = msg.substring(0, 100);
|
||||
|
||||
int count = 10;
|
||||
for (int i = 0; i < count; i++) {
|
||||
this.sendMessage(msg);
|
||||
}
|
||||
|
||||
String frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
frame = receiveFrame(10000);
|
||||
|
||||
Assert.assertTrue(frame.startsWith("CONNECTED"));
|
||||
|
||||
frame = "SUBSCRIBE\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n" + "ack:auto\n\nfff" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
frame = receiveFrame(60000);
|
||||
Assert.assertNotNull(frame);
|
||||
System.out.println("part of frame: " + frame.substring(0, 250));
|
||||
Assert.assertTrue(frame.startsWith("MESSAGE"));
|
||||
Assert.assertTrue(frame.indexOf("destination:") > 0);
|
||||
int index = frame.indexOf(leadingPart);
|
||||
assertEquals(msg.length(), (frame.length() - index));
|
||||
}
|
||||
|
||||
// remove suscription
|
||||
frame = "UNSUBSCRIBE\n" + "destination:" +
|
||||
getQueuePrefix() +
|
||||
getQueueName() +
|
||||
"\n" +
|
||||
"receipt:567\n" +
|
||||
"\n\n" +
|
||||
Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
waitForReceipt();
|
||||
|
||||
frame = "DISCONNECT\n" + "\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw ex;
|
||||
} finally {
|
||||
cleanUp();
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
protected JMSServerManager createPersistentServerWithStompMinLargeSize(int sz) throws Exception {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put(TransportConstants.PROTOCOLS_PROP_NAME, StompProtocolManagerFactory.STOMP_PROTOCOL_NAME);
|
||||
params.put(TransportConstants.PORT_PROP_NAME, TransportConstants.DEFAULT_STOMP_PORT);
|
||||
params.put(TransportConstants.STOMP_CONSUMERS_CREDIT, "-1");
|
||||
params.put(TransportConstants.STOMP_MIN_LARGE_MESSAGE_SIZE, sz);
|
||||
TransportConfiguration stompTransport = new TransportConfiguration(NettyAcceptorFactory.class.getName(), params);
|
||||
|
||||
Configuration config = createBasicConfig().setPersistenceEnabled(true).addAcceptorConfiguration(stompTransport).addAcceptorConfiguration(new TransportConfiguration(InVMAcceptorFactory.class.getName()));
|
||||
|
||||
ActiveMQServer activeMQServer = addServer(ActiveMQServers.newActiveMQServer(config, defUser, defPass));
|
||||
|
||||
JMSConfiguration jmsConfig = new JMSConfigurationImpl();
|
||||
jmsConfig.getQueueConfigurations().add(new JMSQueueConfigurationImpl().setName(getQueueName()).setBindings(getQueueName()));
|
||||
jmsConfig.getTopicConfigurations().add(new TopicConfigurationImpl().setName(getTopicName()).setBindings(getTopicName()));
|
||||
server = new JMSServerManagerImpl(activeMQServer, jmsConfig);
|
||||
server.setRegistry(new JndiBindingRegistry((new InVMNamingContext())));
|
||||
return server;
|
||||
}
|
||||
|
||||
private void enableMessageIDTest(Boolean enable) throws Exception {
|
||||
try {
|
||||
server = createServerWithExtraStompOptions(null, enable);
|
||||
server.start();
|
||||
|
||||
setUpAfterServer();
|
||||
|
||||
String connect_frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n" + "request-id: 1\n" + "\n" + Stomp.NULL;
|
||||
sendFrame(connect_frame);
|
||||
|
||||
String f = receiveFrame(10000);
|
||||
Assert.assertTrue(f.startsWith("CONNECTED"));
|
||||
Assert.assertTrue(f.indexOf("response-id:1") >= 0);
|
||||
|
||||
String frame = "SEND\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n\n" + "Hello World 1" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
|
||||
frame = "SEND\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n\n" + "Hello World 2" + Stomp.NULL;
|
||||
|
||||
sendFrame(frame);
|
||||
|
||||
QueueBrowser browser = session.createBrowser(queue);
|
||||
|
||||
Enumeration enu = browser.getEnumeration();
|
||||
|
||||
while (enu.hasMoreElements()) {
|
||||
Message msg = (Message) enu.nextElement();
|
||||
String msgId = msg.getStringProperty("amqMessageId");
|
||||
if (enable != null && enable.booleanValue()) {
|
||||
assertNotNull(msgId);
|
||||
assertTrue(msgId.indexOf("STOMP") == 0);
|
||||
} else {
|
||||
assertNull(msgId);
|
||||
}
|
||||
}
|
||||
|
||||
browser.close();
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
|
||||
TextMessage message = (TextMessage) consumer.receive(1000);
|
||||
Assert.assertNotNull(message);
|
||||
|
||||
message = (TextMessage) consumer.receive(1000);
|
||||
Assert.assertNotNull(message);
|
||||
|
||||
message = (TextMessage) consumer.receive(2000);
|
||||
Assert.assertNull(message);
|
||||
} finally {
|
||||
cleanUp();
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
protected JMSServerManager createServerWithTTL(String ttl) throws Exception {
|
||||
return createServerWithExtraStompOptions(ttl, null);
|
||||
}
|
||||
|
||||
protected JMSServerManager createServerWithExtraStompOptions(String ttl, Boolean enableMessageID) throws Exception {
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put(TransportConstants.PROTOCOLS_PROP_NAME, StompProtocolManagerFactory.STOMP_PROTOCOL_NAME);
|
||||
params.put(TransportConstants.PORT_PROP_NAME, TransportConstants.DEFAULT_STOMP_PORT);
|
||||
if (ttl != null) {
|
||||
params.put(TransportConstants.CONNECTION_TTL, ttl);
|
||||
}
|
||||
if (enableMessageID != null) {
|
||||
params.put(TransportConstants.STOMP_ENABLE_MESSAGE_ID, enableMessageID);
|
||||
}
|
||||
params.put(TransportConstants.STOMP_CONSUMERS_CREDIT, "-1");
|
||||
TransportConfiguration stompTransport = new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params);
|
||||
|
||||
Configuration config = createBasicConfig().setPersistenceEnabled(false).addAcceptorConfiguration(stompTransport).addAcceptorConfiguration(new TransportConfiguration(INVM_ACCEPTOR_FACTORY));
|
||||
|
||||
ActiveMQServer activeMQServer = addServer(ActiveMQServers.newActiveMQServer(config, defUser, defPass));
|
||||
|
||||
JMSConfiguration jmsConfig = new JMSConfigurationImpl();
|
||||
jmsConfig.getQueueConfigurations().add(new JMSQueueConfigurationImpl().setName(getQueueName()).setDurable(false).setBindings(getQueueName()));
|
||||
jmsConfig.getTopicConfigurations().add(new TopicConfigurationImpl().setName(getTopicName()).setBindings(getTopicName()));
|
||||
server = new JMSServerManagerImpl(activeMQServer, jmsConfig);
|
||||
server.setRegistry(new JndiBindingRegistry(new InVMNamingContext()));
|
||||
return server;
|
||||
}
|
||||
|
||||
public static class MyCoreInterceptor implements Interceptor {
|
||||
|
||||
static List<Packet> incomingInterceptedFrames = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public boolean intercept(Packet packet, RemotingConnection connection) {
|
||||
incomingInterceptedFrames.add(packet);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class MyIncomingStompFrameInterceptor implements StompFrameInterceptor {
|
||||
|
||||
static List<StompFrame> incomingInterceptedFrames = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public boolean intercept(StompFrame stompFrame, RemotingConnection connection) {
|
||||
incomingInterceptedFrames.add(stompFrame);
|
||||
stompFrame.addHeader("incomingInterceptedProp", "incomingInterceptedVal");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MyOutgoingStompFrameInterceptor implements StompFrameInterceptor {
|
||||
|
||||
static List<StompFrame> outgoingInterceptedFrames = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public boolean intercept(StompFrame stompFrame, RemotingConnection connection) {
|
||||
outgoingInterceptedFrames.add(stompFrame);
|
||||
stompFrame.addHeader("outgoingInterceptedProp", "outgoingInterceptedVal");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stompFrameInterceptor() throws Exception {
|
||||
MyIncomingStompFrameInterceptor.incomingInterceptedFrames.clear();
|
||||
MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.clear();
|
||||
try {
|
||||
List<String> incomingInterceptorList = new ArrayList<>();
|
||||
incomingInterceptorList.add("org.apache.activemq.artemis.tests.integration.stomp.ExtraStompTest$MyIncomingStompFrameInterceptor");
|
||||
incomingInterceptorList.add("org.apache.activemq.artemis.tests.integration.stomp.ExtraStompTest$MyCoreInterceptor");
|
||||
List<String> outgoingInterceptorList = new ArrayList<>();
|
||||
outgoingInterceptorList.add("org.apache.activemq.artemis.tests.integration.stomp.ExtraStompTest$MyOutgoingStompFrameInterceptor");
|
||||
|
||||
server = createServerWithStompInterceptor(incomingInterceptorList, outgoingInterceptorList);
|
||||
server.start();
|
||||
|
||||
setUpAfterServer(); // This will make some calls through core
|
||||
|
||||
// So we clear them here
|
||||
MyCoreInterceptor.incomingInterceptedFrames.clear();
|
||||
|
||||
String frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
|
||||
frame = receiveFrame(100000);
|
||||
|
||||
frame = "SUBSCRIBE\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n" + "ack:auto\n\nfff" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
|
||||
assertEquals(0, MyCoreInterceptor.incomingInterceptedFrames.size());
|
||||
sendMessage(getName());
|
||||
|
||||
// Something was supposed to be called on sendMessages
|
||||
assertTrue("core interceptor is not working", MyCoreInterceptor.incomingInterceptedFrames.size() > 0);
|
||||
|
||||
receiveFrame(10000);
|
||||
|
||||
frame = "SEND\n" + "destination:" +
|
||||
getQueuePrefix() +
|
||||
getQueueName() +
|
||||
"\n\n" +
|
||||
"Hello World" +
|
||||
Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
|
||||
receiveFrame(10000);
|
||||
|
||||
frame = "DISCONNECT\n" + "\n\n" + Stomp.NULL;
|
||||
|
||||
sendFrame(frame);
|
||||
|
||||
} finally {
|
||||
cleanUp();
|
||||
server.stop();
|
||||
}
|
||||
|
||||
List<String> incomingCommands = new ArrayList<>(4);
|
||||
incomingCommands.add("CONNECT");
|
||||
incomingCommands.add("SUBSCRIBE");
|
||||
incomingCommands.add("SEND");
|
||||
incomingCommands.add("DISCONNECT");
|
||||
|
||||
List<String> outgoingCommands = new ArrayList<>(3);
|
||||
outgoingCommands.add("CONNECTED");
|
||||
outgoingCommands.add("MESSAGE");
|
||||
outgoingCommands.add("MESSAGE");
|
||||
|
||||
long timeout = System.currentTimeMillis() + 1000;
|
||||
|
||||
// Things are async, giving some time to things arrive before we actually assert
|
||||
while (MyIncomingStompFrameInterceptor.incomingInterceptedFrames.size() < 4 &&
|
||||
MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.size() < 3 &&
|
||||
timeout > System.currentTimeMillis()) {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
Assert.assertEquals(4, MyIncomingStompFrameInterceptor.incomingInterceptedFrames.size());
|
||||
Assert.assertEquals(3, MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.size());
|
||||
|
||||
for (int i = 0; i < MyIncomingStompFrameInterceptor.incomingInterceptedFrames.size(); i++) {
|
||||
Assert.assertEquals(incomingCommands.get(i), MyIncomingStompFrameInterceptor.incomingInterceptedFrames.get(i).getCommand());
|
||||
Assert.assertEquals("incomingInterceptedVal", MyIncomingStompFrameInterceptor.incomingInterceptedFrames.get(i).getHeader("incomingInterceptedProp"));
|
||||
}
|
||||
|
||||
for (int i = 0; i < MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.size(); i++) {
|
||||
Assert.assertEquals(outgoingCommands.get(i), MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.get(i).getCommand());
|
||||
}
|
||||
|
||||
Assert.assertEquals("incomingInterceptedVal", MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.get(2).getHeader("incomingInterceptedProp"));
|
||||
Assert.assertEquals("outgoingInterceptedVal", MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.get(2).getHeader("outgoingInterceptedProp"));
|
||||
}
|
||||
|
||||
protected JMSServerManager createServerWithStompInterceptor(List<String> stompIncomingInterceptor,
|
||||
List<String> stompOutgoingInterceptor) throws Exception {
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put(TransportConstants.PROTOCOLS_PROP_NAME, StompProtocolManagerFactory.STOMP_PROTOCOL_NAME);
|
||||
params.put(TransportConstants.PORT_PROP_NAME, TransportConstants.DEFAULT_STOMP_PORT);
|
||||
params.put(TransportConstants.STOMP_CONSUMERS_CREDIT, "-1");
|
||||
TransportConfiguration stompTransport = new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params);
|
||||
|
||||
Configuration config = createBasicConfig().setPersistenceEnabled(false).addAcceptorConfiguration(stompTransport).addAcceptorConfiguration(new TransportConfiguration(INVM_ACCEPTOR_FACTORY)).setIncomingInterceptorClassNames(stompIncomingInterceptor).setOutgoingInterceptorClassNames(stompOutgoingInterceptor);
|
||||
|
||||
ActiveMQServer hornetQServer = addServer(ActiveMQServers.newActiveMQServer(config, defUser, defPass));
|
||||
|
||||
JMSConfiguration jmsConfig = new JMSConfigurationImpl();
|
||||
jmsConfig.getQueueConfigurations().add(new JMSQueueConfigurationImpl().setName(getQueueName()).setDurable(false).setBindings(getQueueName()));
|
||||
jmsConfig.getTopicConfigurations().add(new TopicConfigurationImpl().setName(getTopicName()).setBindings(getTopicName()));
|
||||
server = new JMSServerManagerImpl(hornetQServer, jmsConfig);
|
||||
server.setRegistry(new JndiBindingRegistry(new InVMNamingContext()));
|
||||
return server;
|
||||
}
|
||||
|
||||
}
|
|
@ -19,32 +19,20 @@ package org.apache.activemq.artemis.tests.integration.stomp;
|
|||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
|
||||
import org.apache.activemq.artemis.jms.server.JMSServerManager;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
|
||||
import org.junit.Test;
|
||||
|
||||
public class StompConnectionCleanupTest extends StompTestBase {
|
||||
public class StompConnectionCleanupTest extends StompTest {
|
||||
|
||||
private static final long CONNECTION_TTL = 2000;
|
||||
|
||||
// ARTEMIS-231
|
||||
@Test
|
||||
public void testConnectionCleanupWithTopicSubscription() throws Exception {
|
||||
String frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
frame = receiveFrame(10000);
|
||||
conn.connect(defUser, defPass);
|
||||
|
||||
//We send and consumer a message to ensure a STOMP connection and server session is created
|
||||
|
||||
System.out.println("Received frame: " + frame);
|
||||
|
||||
assertTrue(frame.startsWith("CONNECTED"));
|
||||
|
||||
frame = "SUBSCRIBE\n" + "destination:" + getTopicPrefix() + getTopicName() + "\n" + "ack:auto\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
|
||||
frame = "DISCONNECT\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
subscribeTopic(conn, null, "auto", null);
|
||||
|
||||
// Now we wait until the connection is cleared on the server, which will happen some time after ttl, since no data
|
||||
// is being sent
|
||||
|
@ -72,25 +60,16 @@ public class StompConnectionCleanupTest extends StompTestBase {
|
|||
|
||||
@Test
|
||||
public void testConnectionCleanup() throws Exception {
|
||||
String frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
frame = receiveFrame(10000);
|
||||
conn.connect(defUser, defPass);
|
||||
|
||||
//We send and consumer a message to ensure a STOMP connection and server session is created
|
||||
subscribe(conn, null, "auto", null);
|
||||
|
||||
System.out.println("Received frame: " + frame);
|
||||
send(conn, getQueuePrefix() + getQueueName(), null, "Hello World");
|
||||
|
||||
assertTrue(frame.startsWith("CONNECTED"));
|
||||
ClientStompFrame frame = conn.receiveFrame(10000);
|
||||
|
||||
frame = "SUBSCRIBE\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n" + "ack:auto\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
|
||||
frame = "SEND\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n\n" + "Hello World" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
|
||||
frame = receiveFrame(10000);
|
||||
assertTrue(frame.startsWith("MESSAGE"));
|
||||
assertTrue(frame.indexOf("destination:") > 0);
|
||||
assertTrue(frame.getCommand().equals("MESSAGE"));
|
||||
assertTrue(frame.getHeader("destination").equals(getQueuePrefix() + getQueueName()));
|
||||
|
||||
// Now we wait until the connection is cleared on the server, which will happen some time after ttl, since no data
|
||||
// is being sent
|
||||
|
@ -118,13 +97,7 @@ public class StompConnectionCleanupTest extends StompTestBase {
|
|||
|
||||
@Test
|
||||
public void testConnectionNotCleanedUp() throws Exception {
|
||||
String frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
frame = receiveFrame(10000);
|
||||
|
||||
//We send and consumer a message to ensure a STOMP connection and server session is created
|
||||
|
||||
assertTrue(frame.startsWith("CONNECTED"));
|
||||
conn.connect(defUser, defPass);
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
|
||||
|
@ -136,8 +109,7 @@ public class StompConnectionCleanupTest extends StompTestBase {
|
|||
while (true) {
|
||||
//Send and receive a msg
|
||||
|
||||
frame = "SEND\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n\n" + "Hello World" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
send(conn, getQueuePrefix() + getQueueName(), null, "Hello World");
|
||||
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
|
|
|
@ -1,78 +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.tests.integration.stomp;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
||||
import io.netty.handler.codec.http.DefaultHttpContent;
|
||||
import io.netty.handler.codec.http.FullHttpRequest;
|
||||
import io.netty.handler.codec.http.HttpHeaders;
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import io.netty.handler.codec.http.HttpRequestEncoder;
|
||||
import io.netty.handler.codec.http.HttpResponseDecoder;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import io.netty.handler.codec.string.StringDecoder;
|
||||
import io.netty.handler.codec.string.StringEncoder;
|
||||
|
||||
public class StompOverHttpTest extends StompTest {
|
||||
|
||||
@Override
|
||||
protected void addChannelHandlers(int index, SocketChannel ch) {
|
||||
ch.pipeline().addLast(new HttpRequestEncoder());
|
||||
ch.pipeline().addLast(new HttpResponseDecoder());
|
||||
ch.pipeline().addLast(new HttpHandler());
|
||||
ch.pipeline().addLast("decoder", new StringDecoder(StandardCharsets.UTF_8));
|
||||
ch.pipeline().addLast("encoder", new StringEncoder(StandardCharsets.UTF_8));
|
||||
ch.pipeline().addLast(new StompClientHandler(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String receiveFrame(long timeOut) throws Exception {
|
||||
//we are request/response so may need to send an empty request so we get responses piggy backed
|
||||
sendFrame(new byte[]{});
|
||||
return super.receiveFrame(timeOut);
|
||||
}
|
||||
|
||||
class HttpHandler extends ChannelDuplexHandler {
|
||||
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||
if (msg instanceof DefaultHttpContent) {
|
||||
DefaultHttpContent response = (DefaultHttpContent) msg;
|
||||
ctx.fireChannelRead(response.content());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ChannelHandlerContext ctx, final Object msg, ChannelPromise promise) throws Exception {
|
||||
if (msg instanceof ByteBuf) {
|
||||
ByteBuf buf = (ByteBuf) msg;
|
||||
FullHttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "", buf);
|
||||
httpRequest.headers().add(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf.readableBytes()));
|
||||
ctx.write(httpRequest, promise);
|
||||
} else {
|
||||
ctx.write(msg, promise);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,151 +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.tests.integration.stomp;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelDuplexHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.handler.codec.http.HttpClientCodec;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||
import io.netty.handler.codec.string.StringDecoder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class StompOverWebsocketTest extends StompTest {
|
||||
|
||||
private ChannelPromise handshakeFuture;
|
||||
|
||||
private final boolean useBinaryFrames;
|
||||
|
||||
@Parameterized.Parameters(name = "useBinaryFrames={0}")
|
||||
public static Collection<Object[]> data() {
|
||||
List<Object[]> list = Arrays.asList(new Object[][]{{Boolean.TRUE}, {Boolean.FALSE}});
|
||||
return list;
|
||||
}
|
||||
|
||||
public StompOverWebsocketTest(Boolean useBinaryFrames) {
|
||||
super();
|
||||
this.useBinaryFrames = useBinaryFrames;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addChannelHandlers(int index, SocketChannel ch) throws URISyntaxException {
|
||||
ch.pipeline().addLast("http-codec", new HttpClientCodec());
|
||||
ch.pipeline().addLast("aggregator", new HttpObjectAggregator(8192));
|
||||
ch.pipeline().addLast(new WebsocketHandler(WebSocketClientHandshakerFactory.newHandshaker(new URI("ws://localhost:8080/websocket"), WebSocketVersion.V13, null, false, null)));
|
||||
ch.pipeline().addLast("decoder", new StringDecoder(StandardCharsets.UTF_8));
|
||||
ch.pipeline().addLast(new StompClientHandler(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handshake() throws InterruptedException {
|
||||
handshakeFuture.sync();
|
||||
}
|
||||
|
||||
class WebsocketHandler extends ChannelDuplexHandler {
|
||||
|
||||
private WebSocketClientHandshaker handshaker;
|
||||
|
||||
WebsocketHandler(WebSocketClientHandshaker webSocketClientHandshaker) {
|
||||
this.handshaker = webSocketClientHandshaker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
|
||||
handshakeFuture = ctx.newPromise();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
handshaker.handshake(ctx.channel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
System.out.println("WebSocket Client disconnected!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
Channel ch = ctx.channel();
|
||||
if (!handshaker.isHandshakeComplete()) {
|
||||
handshaker.finishHandshake(ch, (FullHttpResponse) msg);
|
||||
System.out.println("WebSocket Client connected!");
|
||||
handshakeFuture.setSuccess();
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg instanceof FullHttpResponse) {
|
||||
FullHttpResponse response = (FullHttpResponse) msg;
|
||||
throw new Exception("Unexpected FullHttpResponse (getStatus=" + response.getStatus() + ", content=" + response.content().toString(StandardCharsets.UTF_8) + ')');
|
||||
}
|
||||
|
||||
WebSocketFrame frame = (WebSocketFrame) msg;
|
||||
if (frame instanceof BinaryWebSocketFrame) {
|
||||
BinaryWebSocketFrame dataFrame = (BinaryWebSocketFrame) frame;
|
||||
super.channelRead(ctx, dataFrame.content());
|
||||
} else if (frame instanceof PongWebSocketFrame) {
|
||||
System.out.println("WebSocket Client received pong");
|
||||
} else if (frame instanceof CloseWebSocketFrame) {
|
||||
System.out.println("WebSocket Client received closing");
|
||||
ch.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
try {
|
||||
if (msg instanceof String) {
|
||||
ctx.write(createFrame((String) msg), promise);
|
||||
} else {
|
||||
super.write(ctx, msg, promise);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected WebSocketFrame createFrame(String msg) {
|
||||
if (useBinaryFrames) {
|
||||
return new BinaryWebSocketFrame(Unpooled.copiedBuffer(msg, StandardCharsets.UTF_8));
|
||||
} else {
|
||||
return new TextWebSocketFrame(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -26,34 +26,17 @@ import javax.jms.Session;
|
|||
import javax.jms.TextMessage;
|
||||
import javax.jms.Topic;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.string.StringDecoder;
|
||||
import io.netty.handler.codec.string.StringEncoder;
|
||||
import org.apache.activemq.artemis.api.core.TransportConfiguration;
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.protocol.mqtt.MQTTProtocolManagerFactory;
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.StompProtocolManagerFactory;
|
||||
import org.apache.activemq.artemis.core.registry.JndiBindingRegistry;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory;
|
||||
|
@ -63,6 +46,7 @@ import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
|
|||
import org.apache.activemq.artemis.core.security.Role;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServers;
|
||||
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
|
||||
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;
|
||||
import org.apache.activemq.artemis.jms.server.JMSServerManager;
|
||||
|
@ -73,13 +57,16 @@ import org.apache.activemq.artemis.jms.server.config.impl.TopicConfigurationImpl
|
|||
import org.apache.activemq.artemis.jms.server.impl.JMSServerManagerImpl;
|
||||
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
|
||||
import org.apache.activemq.artemis.tests.integration.IntegrationTestLogger;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnection;
|
||||
import org.apache.activemq.artemis.tests.unit.util.InVMNamingContext;
|
||||
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
public abstract class StompTestBase extends ActiveMQTestBase {
|
||||
|
||||
protected String hostname = "127.0.0.1";
|
||||
|
||||
protected final int port = 61613;
|
||||
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
@ -98,98 +85,56 @@ public abstract class StompTestBase extends ActiveMQTestBase {
|
|||
|
||||
protected String defPass = "wombats";
|
||||
|
||||
protected boolean autoCreateServer = true;
|
||||
|
||||
private List<Bootstrap> bootstraps = new ArrayList<>();
|
||||
|
||||
// private Channel channel;
|
||||
|
||||
private List<BlockingQueue<String>> priorityQueues = new ArrayList<>();
|
||||
|
||||
private List<EventLoopGroup> groups = new ArrayList<>();
|
||||
|
||||
private List<Channel> channels = new ArrayList<>();
|
||||
|
||||
// Implementation methods
|
||||
// -------------------------------------------------------------------------
|
||||
public boolean isCompressLargeMessages() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSecurityEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPersistenceEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isEnableStompMessageId() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Integer getStompMinLargeMessageSize() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getIncomingInterceptors() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getOutgoingInterceptors() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
if (autoCreateServer) {
|
||||
server = createServer();
|
||||
addServer(server.getActiveMQServer());
|
||||
server.start();
|
||||
connectionFactory = createConnectionFactory();
|
||||
createBootstrap();
|
||||
|
||||
if (isSecurityEnabled()) {
|
||||
connection = connectionFactory.createConnection("brianm", "wombats");
|
||||
} else {
|
||||
connection = connectionFactory.createConnection();
|
||||
}
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
queue = session.createQueue(getQueueName());
|
||||
topic = session.createTopic(getTopicName());
|
||||
connection.start();
|
||||
}
|
||||
}
|
||||
|
||||
private void createBootstrap() {
|
||||
createBootstrap(0, port);
|
||||
}
|
||||
|
||||
protected void createBootstrap(int port) {
|
||||
createBootstrap(0, port);
|
||||
}
|
||||
|
||||
protected void createBootstrap(final int index, int port) {
|
||||
priorityQueues.add(index, new ArrayBlockingQueue<String>(1000));
|
||||
groups.add(index, new NioEventLoopGroup());
|
||||
bootstraps.add(index, new Bootstrap());
|
||||
bootstraps.get(index).group(groups.get(index)).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
public void initChannel(SocketChannel ch) throws Exception {
|
||||
addChannelHandlers(index, ch);
|
||||
}
|
||||
});
|
||||
|
||||
// Start the client.
|
||||
try {
|
||||
channels.add(index, bootstraps.get(index).connect("localhost", port).sync().channel());
|
||||
handshake();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void handshake() throws InterruptedException {
|
||||
}
|
||||
|
||||
protected void addChannelHandlers(int index, SocketChannel ch) throws URISyntaxException {
|
||||
ch.pipeline().addLast("decoder", new StringDecoder(StandardCharsets.UTF_8));
|
||||
ch.pipeline().addLast("encoder", new StringEncoder(StandardCharsets.UTF_8));
|
||||
ch.pipeline().addLast(new StompClientHandler(index));
|
||||
}
|
||||
|
||||
protected void setUpAfterServer() throws Exception {
|
||||
setUpAfterServer(false);
|
||||
}
|
||||
|
||||
protected void setUpAfterServer(boolean jmsCompressLarge) throws Exception {
|
||||
server = createServer();
|
||||
server.start();
|
||||
connectionFactory = createConnectionFactory();
|
||||
ActiveMQConnectionFactory activeMQConnectionFactory = (ActiveMQConnectionFactory) connectionFactory;
|
||||
|
||||
activeMQConnectionFactory.setCompressLargeMessage(jmsCompressLarge);
|
||||
createBootstrap();
|
||||
((ActiveMQConnectionFactory)connectionFactory).setCompressLargeMessage(isCompressLargeMessages());
|
||||
|
||||
connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
if (isSecurityEnabled()) {
|
||||
connection = connectionFactory.createConnection("brianm", "wombats");
|
||||
} else {
|
||||
connection = connectionFactory.createConnection();
|
||||
}
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
queue = session.createQueue(getQueueName());
|
||||
topic = session.createTopic(getTopicName());
|
||||
|
||||
connection.start();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -198,14 +143,30 @@ public abstract class StompTestBase extends ActiveMQTestBase {
|
|||
*/
|
||||
protected JMSServerManager createServer() throws Exception {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put(TransportConstants.PROTOCOLS_PROP_NAME, StompProtocolManagerFactory.STOMP_PROTOCOL_NAME);
|
||||
params.put(TransportConstants.PROTOCOLS_PROP_NAME, StompProtocolManagerFactory.STOMP_PROTOCOL_NAME + "," + MQTTProtocolManagerFactory.MQTT_PROTOCOL_NAME);
|
||||
params.put(TransportConstants.PORT_PROP_NAME, TransportConstants.DEFAULT_STOMP_PORT);
|
||||
params.put(TransportConstants.STOMP_CONSUMERS_CREDIT, "-1");
|
||||
if (isEnableStompMessageId()) {
|
||||
params.put(TransportConstants.STOMP_ENABLE_MESSAGE_ID, true);
|
||||
}
|
||||
if (getStompMinLargeMessageSize() != null) {
|
||||
params.put(TransportConstants.STOMP_MIN_LARGE_MESSAGE_SIZE, 2048);
|
||||
}
|
||||
TransportConfiguration stompTransport = new TransportConfiguration(NettyAcceptorFactory.class.getName(), params);
|
||||
TransportConfiguration allTransport = new TransportConfiguration(NettyAcceptorFactory.class.getName());
|
||||
|
||||
Configuration config = createBasicConfig().setSecurityEnabled(isSecurityEnabled()).setPersistenceEnabled(true).addAcceptorConfiguration(stompTransport).addAcceptorConfiguration(new TransportConfiguration(InVMAcceptorFactory.class.getName()));
|
||||
config.addAcceptorConfiguration(allTransport);
|
||||
Configuration config = createBasicConfig().setSecurityEnabled(isSecurityEnabled())
|
||||
.setPersistenceEnabled(isPersistenceEnabled())
|
||||
.addAcceptorConfiguration(stompTransport)
|
||||
.addAcceptorConfiguration(new TransportConfiguration(InVMAcceptorFactory.class.getName()))
|
||||
.setConnectionTtlCheckInterval(500);
|
||||
|
||||
if (getIncomingInterceptors() != null) {
|
||||
config.setIncomingInterceptorClassNames(getIncomingInterceptors());
|
||||
}
|
||||
|
||||
if (getOutgoingInterceptors() != null) {
|
||||
config.setOutgoingInterceptorClassNames(getOutgoingInterceptors());
|
||||
}
|
||||
|
||||
ActiveMQServer activeMQServer = addServer(ActiveMQServers.newActiveMQServer(config, defUser, defPass));
|
||||
|
||||
|
@ -222,62 +183,19 @@ public abstract class StompTestBase extends ActiveMQTestBase {
|
|||
}
|
||||
|
||||
JMSConfiguration jmsConfig = new JMSConfigurationImpl();
|
||||
jmsConfig.getQueueConfigurations().add(new JMSQueueConfigurationImpl().setName(getQueueName()).setDurable(false).setBindings(getQueueName()));
|
||||
jmsConfig.getQueueConfigurations().add(new JMSQueueConfigurationImpl().setName(getQueueName()).setBindings(getQueueName()));
|
||||
jmsConfig.getTopicConfigurations().add(new TopicConfigurationImpl().setName(getTopicName()).setBindings(getTopicName()));
|
||||
server = new JMSServerManagerImpl(activeMQServer, jmsConfig);
|
||||
server.setRegistry(new JndiBindingRegistry(new InVMNamingContext()));
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (autoCreateServer) {
|
||||
connection.close();
|
||||
|
||||
for (EventLoopGroup group : groups) {
|
||||
if (group != null) {
|
||||
for (Channel channel : channels) {
|
||||
channel.close();
|
||||
}
|
||||
group.shutdownGracefully(0, 5000, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
protected void cleanUp() throws Exception {
|
||||
connection.close();
|
||||
if (groups.get(0) != null) {
|
||||
groups.get(0).shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
protected void reconnect() throws Exception {
|
||||
reconnect(0);
|
||||
}
|
||||
|
||||
protected void reconnect(long sleep) throws Exception {
|
||||
groups.get(0).shutdown();
|
||||
|
||||
if (sleep > 0) {
|
||||
Thread.sleep(sleep);
|
||||
}
|
||||
|
||||
createBootstrap();
|
||||
}
|
||||
|
||||
protected ConnectionFactory createConnectionFactory() {
|
||||
return new ActiveMQJMSConnectionFactory(false, new TransportConfiguration(InVMConnectorFactory.class.getName()));
|
||||
}
|
||||
|
||||
protected Socket createSocket() throws IOException {
|
||||
return new Socket("localhost", port);
|
||||
}
|
||||
|
||||
protected String getQueueName() {
|
||||
return "test";
|
||||
return "testQueue";
|
||||
}
|
||||
|
||||
protected String getQueuePrefix() {
|
||||
|
@ -292,65 +210,28 @@ public abstract class StompTestBase extends ActiveMQTestBase {
|
|||
return "";
|
||||
}
|
||||
|
||||
protected void assertChannelClosed() throws InterruptedException {
|
||||
assertChannelClosed(0);
|
||||
public void sendJmsMessage(String msg) throws Exception {
|
||||
sendJmsMessage(msg, queue);
|
||||
}
|
||||
|
||||
protected void assertChannelClosed(int index) throws InterruptedException {
|
||||
boolean closed = channels.get(index).closeFuture().await(5000);
|
||||
assertTrue("channel not closed", closed);
|
||||
}
|
||||
|
||||
public void sendFrame(String data) throws Exception {
|
||||
IntegrationTestLogger.LOGGER.info("Sending: " + data);
|
||||
sendFrame(0, data);
|
||||
}
|
||||
|
||||
public void sendFrame(int index, String data) throws Exception {
|
||||
channels.get(index).writeAndFlush(data);
|
||||
}
|
||||
|
||||
public void sendFrame(byte[] data) throws Exception {
|
||||
sendFrame(0, data);
|
||||
}
|
||||
|
||||
public void sendFrame(int index, byte[] data) throws Exception {
|
||||
ByteBuf buffer = Unpooled.buffer(data.length);
|
||||
buffer.writeBytes(data);
|
||||
channels.get(index).writeAndFlush(buffer);
|
||||
}
|
||||
|
||||
public String receiveFrame(long timeOut) throws Exception {
|
||||
return receiveFrame(0, timeOut);
|
||||
}
|
||||
|
||||
public String receiveFrame(int index, long timeOut) throws Exception {
|
||||
String msg = priorityQueues.get(index).poll(timeOut, TimeUnit.MILLISECONDS);
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void sendMessage(String msg) throws Exception {
|
||||
sendMessage(msg, queue);
|
||||
}
|
||||
|
||||
public void sendMessage(String msg, Destination destination) throws Exception {
|
||||
public void sendJmsMessage(String msg, Destination destination) throws Exception {
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
TextMessage message = session.createTextMessage(msg);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
public void sendMessage(byte[] data, Destination destination) throws Exception {
|
||||
sendMessage(data, "foo", "xyz", destination);
|
||||
public void sendJmsMessage(byte[] data, Destination destination) throws Exception {
|
||||
sendJmsMessage(data, "foo", "xyz", destination);
|
||||
}
|
||||
|
||||
public void sendMessage(String msg, String propertyName, String propertyValue) throws Exception {
|
||||
sendMessage(msg.getBytes(StandardCharsets.UTF_8), propertyName, propertyValue, queue);
|
||||
public void sendJmsMessage(String msg, String propertyName, String propertyValue) throws Exception {
|
||||
sendJmsMessage(msg.getBytes(StandardCharsets.UTF_8), propertyName, propertyValue, queue);
|
||||
}
|
||||
|
||||
public void sendMessage(byte[] data,
|
||||
String propertyName,
|
||||
String propertyValue,
|
||||
Destination destination) throws Exception {
|
||||
public void sendJmsMessage(byte[] data,
|
||||
String propertyName,
|
||||
String propertyValue,
|
||||
Destination destination) throws Exception {
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
BytesMessage message = session.createBytesMessage();
|
||||
message.setStringProperty(propertyName, propertyValue);
|
||||
|
@ -358,59 +239,294 @@ public abstract class StompTestBase extends ActiveMQTestBase {
|
|||
producer.send(message);
|
||||
}
|
||||
|
||||
protected void waitForReceipt() throws Exception {
|
||||
String frame = receiveFrame(50000);
|
||||
assertNotNull(frame);
|
||||
assertTrue(frame.indexOf("RECEIPT") > -1);
|
||||
public void abortTransaction(StompClientConnection conn, String txID) throws IOException, InterruptedException {
|
||||
ClientStompFrame abortFrame = conn.createFrame(Stomp.Commands.ABORT)
|
||||
.addHeader(Stomp.Headers.TRANSACTION, txID);
|
||||
|
||||
conn.sendFrame(abortFrame);
|
||||
}
|
||||
|
||||
protected void waitForFrameToTakeEffect() throws InterruptedException {
|
||||
// bit of a dirty hack :)
|
||||
// another option would be to force some kind of receipt to be returned
|
||||
// from the frame
|
||||
Thread.sleep(500);
|
||||
public void beginTransaction(StompClientConnection conn, String txID) throws IOException, InterruptedException {
|
||||
ClientStompFrame beginFrame = conn.createFrame(Stomp.Commands.BEGIN)
|
||||
.addHeader(Stomp.Headers.TRANSACTION, txID);
|
||||
|
||||
conn.sendFrame(beginFrame);
|
||||
}
|
||||
|
||||
public boolean isSecurityEnabled() {
|
||||
return false;
|
||||
public void commitTransaction(StompClientConnection conn, String txID) throws IOException, InterruptedException {
|
||||
commitTransaction(conn, txID, false);
|
||||
}
|
||||
|
||||
class StompClientHandler extends SimpleChannelInboundHandler<String> {
|
||||
|
||||
int index = 0;
|
||||
|
||||
StompClientHandler(int index) {
|
||||
this.index = index;
|
||||
public void commitTransaction(StompClientConnection conn,
|
||||
String txID,
|
||||
boolean receipt) throws IOException, InterruptedException {
|
||||
ClientStompFrame beginFrame = conn.createFrame(Stomp.Commands.COMMIT)
|
||||
.addHeader(Stomp.Headers.TRANSACTION, txID);
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
if (receipt) {
|
||||
beginFrame.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
|
||||
}
|
||||
|
||||
StringBuffer currentMessage = new StringBuffer("");
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
|
||||
currentMessage.append(msg);
|
||||
String fullMessage = currentMessage.toString();
|
||||
if (fullMessage.contains("\0\n")) {
|
||||
int messageEnd = fullMessage.indexOf("\0\n");
|
||||
String actualMessage = fullMessage.substring(0, messageEnd);
|
||||
fullMessage = fullMessage.substring(messageEnd + 2);
|
||||
currentMessage = new StringBuffer("");
|
||||
BlockingQueue queue = priorityQueues.get(index);
|
||||
if (queue == null) {
|
||||
queue = new ArrayBlockingQueue(1000);
|
||||
priorityQueues.add(index, queue);
|
||||
}
|
||||
queue.add(actualMessage);
|
||||
if (fullMessage.length() > 0) {
|
||||
channelRead(ctx, fullMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
cause.printStackTrace();
|
||||
ctx.close();
|
||||
ClientStompFrame resp = conn.sendFrame(beginFrame);
|
||||
if (receipt) {
|
||||
assertEquals(uuid, resp.getHeader(Stomp.Headers.Response.RECEIPT_ID));
|
||||
}
|
||||
}
|
||||
|
||||
public void ack(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
ClientStompFrame messageIdFrame) throws IOException, InterruptedException {
|
||||
String messageID = messageIdFrame.getHeader(Stomp.Headers.Message.MESSAGE_ID);
|
||||
|
||||
ClientStompFrame frame = conn.createFrame(Stomp.Commands.ACK)
|
||||
.addHeader(Stomp.Headers.Message.MESSAGE_ID, messageID);
|
||||
|
||||
if (subscriptionId != null) {
|
||||
frame.addHeader(Stomp.Headers.Ack.SUBSCRIPTION, subscriptionId);
|
||||
}
|
||||
|
||||
ClientStompFrame response = conn.sendFrame(frame);
|
||||
if (response != null) {
|
||||
throw new IOException("failed to ack " + response);
|
||||
}
|
||||
}
|
||||
|
||||
public void ack(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
String mid,
|
||||
String txID) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = conn.createFrame(Stomp.Commands.ACK)
|
||||
.addHeader(Stomp.Headers.Ack.SUBSCRIPTION, subscriptionId)
|
||||
.addHeader(Stomp.Headers.Message.MESSAGE_ID, mid);
|
||||
if (txID != null) {
|
||||
frame.addHeader(Stomp.Headers.TRANSACTION, txID);
|
||||
}
|
||||
|
||||
conn.sendFrame(frame);
|
||||
}
|
||||
|
||||
public void nack(StompClientConnection conn, String subscriptionId, String messageId) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = conn.createFrame(Stomp.Commands.NACK)
|
||||
.addHeader(Stomp.Headers.Ack.SUBSCRIPTION, subscriptionId)
|
||||
.addHeader(Stomp.Headers.Message.MESSAGE_ID, messageId);
|
||||
|
||||
conn.sendFrame(frame);
|
||||
}
|
||||
|
||||
public ClientStompFrame subscribe(StompClientConnection conn,
|
||||
String subscriptionId) throws IOException, InterruptedException {
|
||||
return subscribe(conn, subscriptionId, Stomp.Headers.Subscribe.AckModeValues.AUTO, null, null);
|
||||
}
|
||||
|
||||
public ClientStompFrame subscribe(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
String ack) throws IOException, InterruptedException {
|
||||
return subscribe(conn, subscriptionId, ack, null, null);
|
||||
}
|
||||
|
||||
public ClientStompFrame subscribe(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
String ack,
|
||||
String durableId) throws IOException, InterruptedException {
|
||||
return subscribe(conn, subscriptionId, ack, durableId, null);
|
||||
}
|
||||
|
||||
public ClientStompFrame subscribe(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
String ack,
|
||||
String durableId,
|
||||
boolean receipt) throws IOException, InterruptedException {
|
||||
return subscribe(conn, subscriptionId, ack, durableId, null, receipt);
|
||||
}
|
||||
|
||||
public ClientStompFrame subscribe(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
String ack,
|
||||
String durableId,
|
||||
String selector) throws IOException, InterruptedException {
|
||||
return subscribe(conn, subscriptionId, ack, durableId, selector, false);
|
||||
}
|
||||
|
||||
public ClientStompFrame subscribe(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
String ack,
|
||||
String durableId,
|
||||
String selector,
|
||||
boolean receipt) throws IOException, InterruptedException {
|
||||
return subscribe(conn, subscriptionId, ack, durableId, selector, getQueuePrefix() + getQueueName(), receipt);
|
||||
}
|
||||
|
||||
public ClientStompFrame subscribe(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
String ack,
|
||||
String durableId,
|
||||
String selector,
|
||||
String destination,
|
||||
boolean receipt) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SUBSCRIBE)
|
||||
.addHeader(Stomp.Headers.Subscribe.SUBSCRIPTION_TYPE, AddressInfo.RoutingType.ANYCAST.toString())
|
||||
.addHeader(Stomp.Headers.Subscribe.DESTINATION, destination);
|
||||
if (subscriptionId != null) {
|
||||
frame.addHeader(Stomp.Headers.Subscribe.ID, subscriptionId);
|
||||
}
|
||||
if (ack != null) {
|
||||
frame.addHeader(Stomp.Headers.Subscribe.ACK_MODE, ack);
|
||||
}
|
||||
if (durableId != null) {
|
||||
frame.addHeader(Stomp.Headers.Subscribe.DURABLE_SUBSCRIPTION_NAME, durableId);
|
||||
}
|
||||
if (selector != null) {
|
||||
frame.addHeader(Stomp.Headers.Subscribe.SELECTOR, selector);
|
||||
}
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
if (receipt) {
|
||||
frame.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
|
||||
}
|
||||
|
||||
frame = conn.sendFrame(frame);
|
||||
|
||||
if (receipt) {
|
||||
assertEquals(uuid, frame.getHeader(Stomp.Headers.Response.RECEIPT_ID));
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
public ClientStompFrame subscribeTopic(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
String ack,
|
||||
String durableId) throws IOException, InterruptedException {
|
||||
return subscribeTopic(conn, subscriptionId, ack, durableId, false);
|
||||
}
|
||||
|
||||
public ClientStompFrame subscribeTopic(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
String ack,
|
||||
String durableId,
|
||||
boolean receipt) throws IOException, InterruptedException {
|
||||
return subscribeTopic(conn, subscriptionId, ack, durableId, receipt, false);
|
||||
}
|
||||
|
||||
public ClientStompFrame subscribeTopic(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
String ack,
|
||||
String durableId,
|
||||
boolean receipt,
|
||||
boolean noLocal) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SUBSCRIBE)
|
||||
.addHeader(Stomp.Headers.Subscribe.SUBSCRIPTION_TYPE, AddressInfo.RoutingType.MULTICAST.toString())
|
||||
.addHeader(Stomp.Headers.Subscribe.DESTINATION, getTopicPrefix() + getTopicName());
|
||||
if (subscriptionId != null) {
|
||||
frame.addHeader(Stomp.Headers.Subscribe.ID, subscriptionId);
|
||||
}
|
||||
if (ack != null) {
|
||||
frame.addHeader(Stomp.Headers.Subscribe.ACK_MODE, ack);
|
||||
}
|
||||
if (durableId != null) {
|
||||
frame.addHeader(Stomp.Headers.Subscribe.DURABLE_SUBSCRIPTION_NAME, durableId);
|
||||
}
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
if (receipt) {
|
||||
frame.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
|
||||
}
|
||||
if (noLocal) {
|
||||
frame.addHeader(Stomp.Headers.Subscribe.NO_LOCAL, "true");
|
||||
}
|
||||
|
||||
frame = conn.sendFrame(frame);
|
||||
|
||||
if (receipt) {
|
||||
assertNotNull("Requested receipt, but response is null", frame);
|
||||
assertTrue(frame.getHeader(Stomp.Headers.Response.RECEIPT_ID).equals(uuid));
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
public ClientStompFrame unsubscribe(StompClientConnection conn, String subscriptionId) throws IOException, InterruptedException {
|
||||
return unsubscribe(conn, subscriptionId, null, false, false);
|
||||
}
|
||||
|
||||
public ClientStompFrame unsubscribe(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
boolean receipt) throws IOException, InterruptedException {
|
||||
return unsubscribe(conn, subscriptionId, null, receipt, false);
|
||||
}
|
||||
|
||||
public ClientStompFrame unsubscribe(StompClientConnection conn,
|
||||
String subscriptionId,
|
||||
String destination,
|
||||
boolean receipt,
|
||||
boolean durable) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = conn.createFrame(Stomp.Commands.UNSUBSCRIBE);
|
||||
if (durable && subscriptionId != null) {
|
||||
frame.addHeader(Stomp.Headers.Unsubscribe.DURABLE_SUBSCRIPTION_NAME, subscriptionId);
|
||||
} else if (!durable && subscriptionId != null) {
|
||||
frame.addHeader(Stomp.Headers.Unsubscribe.ID, subscriptionId);
|
||||
}
|
||||
|
||||
if (destination != null) {
|
||||
frame.addHeader(Stomp.Headers.Unsubscribe.DESTINATION, destination);
|
||||
}
|
||||
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
|
||||
if (receipt) {
|
||||
frame.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
|
||||
}
|
||||
|
||||
frame = conn.sendFrame(frame);
|
||||
|
||||
if (receipt) {
|
||||
assertEquals(Stomp.Responses.RECEIPT, frame.getCommand());
|
||||
assertEquals(uuid, frame.getHeader(Stomp.Headers.Response.RECEIPT_ID));
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
public ClientStompFrame send(StompClientConnection conn, String destination, String contentType, String body) throws IOException, InterruptedException {
|
||||
return send(conn, destination, contentType, body, false);
|
||||
}
|
||||
|
||||
public ClientStompFrame send(StompClientConnection conn, String destination, String contentType, String body, boolean receipt) throws IOException, InterruptedException {
|
||||
return send(conn, destination, contentType, body, receipt, null);
|
||||
}
|
||||
|
||||
public ClientStompFrame send(StompClientConnection conn, String destination, String contentType, String body, boolean receipt, AddressInfo.RoutingType destinationType) throws IOException, InterruptedException {
|
||||
return send(conn, destination, contentType, body, receipt, destinationType, null);
|
||||
}
|
||||
|
||||
public ClientStompFrame send(StompClientConnection conn, String destination, String contentType, String body, boolean receipt, AddressInfo.RoutingType destinationType, String txId) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND)
|
||||
.addHeader(Stomp.Headers.Send.DESTINATION, destination)
|
||||
.setBody(body);
|
||||
|
||||
if (contentType != null) {
|
||||
frame.addHeader(Stomp.Headers.CONTENT_TYPE, contentType);
|
||||
}
|
||||
|
||||
if (destinationType != null) {
|
||||
frame.addHeader(Stomp.Headers.Send.DESTINATION_TYPE, destinationType.toString());
|
||||
}
|
||||
|
||||
if (txId != null) {
|
||||
frame.addHeader(Stomp.Headers.TRANSACTION, txId);
|
||||
}
|
||||
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
|
||||
if (receipt) {
|
||||
frame.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
|
||||
}
|
||||
frame = conn.sendFrame(frame);
|
||||
|
||||
if (receipt) {
|
||||
assertEquals(Stomp.Responses.RECEIPT, frame.getCommand());
|
||||
assertEquals(uuid, frame.getHeader(Stomp.Headers.Response.RECEIPT_ID));
|
||||
}
|
||||
|
||||
IntegrationTestLogger.LOGGER.info("Received: " + frame);
|
||||
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/**
|
||||
* 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.tests.integration.stomp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.Interceptor;
|
||||
import org.apache.activemq.artemis.core.protocol.core.Packet;
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.StompFrame;
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.StompFrameInterceptor;
|
||||
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
|
||||
import org.apache.activemq.artemis.tests.integration.IntegrationTestLogger;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnection;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnectionFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class StompTestWithInterceptors extends StompTestBase {
|
||||
|
||||
@Override
|
||||
public List<String> getIncomingInterceptors() {
|
||||
List<String> stompIncomingInterceptor = new ArrayList<>();
|
||||
stompIncomingInterceptor.add("org.apache.activemq.artemis.tests.integration.stomp.StompTestWithInterceptors$MyIncomingStompFrameInterceptor");
|
||||
stompIncomingInterceptor.add("org.apache.activemq.artemis.tests.integration.stomp.StompTestWithInterceptors$MyCoreInterceptor");
|
||||
|
||||
return stompIncomingInterceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getOutgoingInterceptors() {
|
||||
List<String> stompOutgoingInterceptor = new ArrayList<>();
|
||||
stompOutgoingInterceptor.add("org.apache.activemq.artemis.tests.integration.stomp.StompTestWithInterceptors$MyOutgoingStompFrameInterceptor");
|
||||
|
||||
return stompOutgoingInterceptor;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stompFrameInterceptor() throws Exception {
|
||||
MyIncomingStompFrameInterceptor.incomingInterceptedFrames.clear();
|
||||
MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.clear();
|
||||
|
||||
Thread.sleep(200);
|
||||
|
||||
// So we clear them here
|
||||
MyCoreInterceptor.incomingInterceptedFrames.clear();
|
||||
|
||||
StompClientConnection conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
|
||||
conn.connect(defUser, defPass);
|
||||
|
||||
ClientStompFrame subFrame = conn.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("subscription-type", "ANYCAST");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
conn.sendFrame(subFrame);
|
||||
|
||||
assertEquals(0, MyCoreInterceptor.incomingInterceptedFrames.size());
|
||||
sendJmsMessage(getName());
|
||||
|
||||
// Something was supposed to be called on sendMessages
|
||||
assertTrue("core interceptor is not working", MyCoreInterceptor.incomingInterceptedFrames.size() > 0);
|
||||
|
||||
conn.receiveFrame(10000);
|
||||
|
||||
ClientStompFrame frame = conn.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.setBody("Hello World");
|
||||
conn.sendFrame(frame);
|
||||
|
||||
conn.disconnect();
|
||||
|
||||
List<String> incomingCommands = new ArrayList<>(4);
|
||||
incomingCommands.add("CONNECT");
|
||||
incomingCommands.add("SUBSCRIBE");
|
||||
incomingCommands.add("SEND");
|
||||
incomingCommands.add("DISCONNECT");
|
||||
|
||||
List<String> outgoingCommands = new ArrayList<>(3);
|
||||
outgoingCommands.add("CONNECTED");
|
||||
outgoingCommands.add("MESSAGE");
|
||||
outgoingCommands.add("MESSAGE");
|
||||
|
||||
long timeout = System.currentTimeMillis() + 1000;
|
||||
|
||||
// Things are async, giving some time to things arrive before we actually assert
|
||||
while (MyIncomingStompFrameInterceptor.incomingInterceptedFrames.size() < 4 &&
|
||||
MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.size() < 3 &&
|
||||
timeout > System.currentTimeMillis()) {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
Assert.assertEquals(4, MyIncomingStompFrameInterceptor.incomingInterceptedFrames.size());
|
||||
Assert.assertEquals(3, MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.size());
|
||||
|
||||
for (int i = 0; i < MyIncomingStompFrameInterceptor.incomingInterceptedFrames.size(); i++) {
|
||||
Assert.assertEquals(incomingCommands.get(i), MyIncomingStompFrameInterceptor.incomingInterceptedFrames.get(i).getCommand());
|
||||
Assert.assertEquals("incomingInterceptedVal", MyIncomingStompFrameInterceptor.incomingInterceptedFrames.get(i).getHeader("incomingInterceptedProp"));
|
||||
}
|
||||
|
||||
for (int i = 0; i < MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.size(); i++) {
|
||||
Assert.assertEquals(outgoingCommands.get(i), MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.get(i).getCommand());
|
||||
}
|
||||
|
||||
Assert.assertEquals("incomingInterceptedVal", MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.get(2).getHeader("incomingInterceptedProp"));
|
||||
Assert.assertEquals("outgoingInterceptedVal", MyOutgoingStompFrameInterceptor.outgoingInterceptedFrames.get(2).getHeader("outgoingInterceptedProp"));
|
||||
}
|
||||
|
||||
public static class MyCoreInterceptor implements Interceptor {
|
||||
|
||||
static List<Packet> incomingInterceptedFrames = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public boolean intercept(Packet packet, RemotingConnection connection) {
|
||||
IntegrationTestLogger.LOGGER.info("Core intercepted: " + packet);
|
||||
incomingInterceptedFrames.add(packet);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MyIncomingStompFrameInterceptor implements StompFrameInterceptor {
|
||||
|
||||
static List<StompFrame> incomingInterceptedFrames = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public boolean intercept(StompFrame stompFrame, RemotingConnection connection) {
|
||||
incomingInterceptedFrames.add(stompFrame);
|
||||
stompFrame.addHeader("incomingInterceptedProp", "incomingInterceptedVal");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MyOutgoingStompFrameInterceptor implements StompFrameInterceptor {
|
||||
|
||||
static List<StompFrame> outgoingInterceptedFrames = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public boolean intercept(StompFrame stompFrame, RemotingConnection connection) {
|
||||
outgoingInterceptedFrames.add(stompFrame);
|
||||
stompFrame.addHeader("outgoingInterceptedProp", "outgoingInterceptedVal");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,416 @@
|
|||
/*
|
||||
* 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.tests.integration.stomp;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
|
||||
import org.apache.activemq.artemis.tests.integration.IntegrationTestLogger;
|
||||
import org.apache.activemq.artemis.tests.integration.largemessage.LargeMessageTestBase;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnection;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnectionFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class StompTestWithLargeMessages extends StompTestBase {
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompressLargeMessages() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistenceEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getStompMinLargeMessageSize() {
|
||||
return 2048;
|
||||
}
|
||||
|
||||
//stomp sender -> large -> stomp receiver
|
||||
@Test
|
||||
public void testSendReceiveLargePersistentMessages() throws Exception {
|
||||
StompClientConnection conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
|
||||
conn.connect(defUser, defPass);
|
||||
|
||||
int count = 10;
|
||||
int msgSize = 1024 * 1024;
|
||||
char[] contents = new char[msgSize];
|
||||
for (int i = 0; i < msgSize; i++) {
|
||||
contents[i] = 'A';
|
||||
}
|
||||
String body = new String(contents);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame frame = conn.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("persistent", "true");
|
||||
frame.setBody(body);
|
||||
conn.sendFrame(frame);
|
||||
}
|
||||
|
||||
ClientStompFrame subFrame = conn.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("subscription-type", "ANYCAST");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
conn.sendFrame(subFrame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame frame = conn.receiveFrame(60000);
|
||||
Assert.assertNotNull(frame);
|
||||
System.out.println("part of frame: " + frame.getBody().substring(0, 200));
|
||||
Assert.assertTrue(frame.getCommand().equals("MESSAGE"));
|
||||
Assert.assertTrue(frame.getHeader("destination").equals(getQueuePrefix() + getQueueName()));
|
||||
int index = frame.getBody().indexOf("AAAA");
|
||||
assertEquals(msgSize, (frame.getBody().length() - index));
|
||||
}
|
||||
|
||||
ClientStompFrame unsubFrame = conn.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
unsubFrame.addHeader("receipt", "567");
|
||||
ClientStompFrame response = conn.sendFrame(unsubFrame);
|
||||
assertNotNull(response);
|
||||
assertNotNull(response.getCommand().equals("RECEIPT"));
|
||||
|
||||
conn.disconnect();
|
||||
}
|
||||
|
||||
//core sender -> large -> stomp receiver
|
||||
@Test
|
||||
public void testReceiveLargePersistentMessagesFromCore() throws Exception {
|
||||
StompClientConnection conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
|
||||
conn.connect(defUser, defPass);
|
||||
|
||||
int msgSize = 3 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE;
|
||||
char[] contents = new char[msgSize];
|
||||
for (int i = 0; i < msgSize; i++) {
|
||||
contents[i] = 'B';
|
||||
}
|
||||
String msg = new String(contents);
|
||||
|
||||
int count = 10;
|
||||
for (int i = 0; i < count; i++) {
|
||||
this.sendJmsMessage(msg);
|
||||
}
|
||||
|
||||
ClientStompFrame subFrame = conn.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("subscription-type", "ANYCAST");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
conn.sendFrame(subFrame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame frame = conn.receiveFrame(60000);
|
||||
Assert.assertNotNull(frame);
|
||||
System.out.println("part of frame: " + frame.getBody().substring(0, 200));
|
||||
Assert.assertTrue(frame.getCommand().equals("MESSAGE"));
|
||||
Assert.assertTrue(frame.getHeader("destination").equals(getQueuePrefix() + getQueueName()));
|
||||
int index = frame.getBody().indexOf("BBB");
|
||||
assertEquals(msgSize, (frame.getBody().length() - index));
|
||||
}
|
||||
|
||||
ClientStompFrame unsubFrame = conn.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
unsubFrame.addHeader("receipt", "567");
|
||||
ClientStompFrame response = conn.sendFrame(unsubFrame);
|
||||
assertNotNull(response);
|
||||
assertNotNull(response.getCommand().equals("RECEIPT"));
|
||||
|
||||
conn.disconnect();
|
||||
}
|
||||
|
||||
//stomp v12 sender -> large -> stomp v12 receiver
|
||||
@Test
|
||||
public void testSendReceiveLargePersistentMessagesV12() throws Exception {
|
||||
StompClientConnection connV12 = StompClientConnectionFactory.createClientConnection("1.2", "localhost", port);
|
||||
connV12.connect(defUser, defPass);
|
||||
|
||||
int count = 10;
|
||||
int szBody = 1024 * 1024;
|
||||
char[] contents = new char[szBody];
|
||||
for (int i = 0; i < szBody; i++) {
|
||||
contents[i] = 'A';
|
||||
}
|
||||
String body = new String(contents);
|
||||
|
||||
ClientStompFrame frame = connV12.createFrame("SEND");
|
||||
frame.addHeader("destination-type", "ANYCAST");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("persistent", "true");
|
||||
frame.setBody(body);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
connV12.sendFrame(frame);
|
||||
}
|
||||
|
||||
ClientStompFrame subFrame = connV12.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("subscription-type", "ANYCAST");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
|
||||
connV12.sendFrame(subFrame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame receiveFrame = connV12.receiveFrame(30000);
|
||||
|
||||
Assert.assertNotNull(receiveFrame);
|
||||
System.out.println("part of frame: " + receiveFrame.getBody().substring(0, 20));
|
||||
Assert.assertTrue(receiveFrame.getCommand().equals("MESSAGE"));
|
||||
Assert.assertEquals(receiveFrame.getHeader("destination"), getQueuePrefix() + getQueueName());
|
||||
assertEquals(szBody, receiveFrame.getBody().length());
|
||||
}
|
||||
|
||||
// remove susbcription
|
||||
ClientStompFrame unsubFrame = connV12.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV12.sendFrame(unsubFrame);
|
||||
|
||||
connV12.disconnect();
|
||||
}
|
||||
|
||||
//core sender -> large -> stomp v12 receiver
|
||||
@Test
|
||||
public void testReceiveLargePersistentMessagesFromCoreV12() throws Exception {
|
||||
int msgSize = 3 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE;
|
||||
char[] contents = new char[msgSize];
|
||||
for (int i = 0; i < msgSize; i++) {
|
||||
contents[i] = 'B';
|
||||
}
|
||||
String msg = new String(contents);
|
||||
|
||||
int count = 10;
|
||||
for (int i = 0; i < count; i++) {
|
||||
this.sendJmsMessage(msg);
|
||||
}
|
||||
|
||||
StompClientConnection connV12 = StompClientConnectionFactory.createClientConnection("1.2", "localhost", port);
|
||||
connV12.connect(defUser, defPass);
|
||||
|
||||
ClientStompFrame subFrame = connV12.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("subscription-type", "ANYCAST");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
connV12.sendFrame(subFrame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame receiveFrame = connV12.receiveFrame(30000);
|
||||
|
||||
Assert.assertNotNull(receiveFrame);
|
||||
System.out.println("part of frame: " + receiveFrame.getBody().substring(0, 20));
|
||||
Assert.assertTrue(receiveFrame.getCommand().equals("MESSAGE"));
|
||||
Assert.assertEquals(receiveFrame.getHeader("destination"), getQueuePrefix() + getQueueName());
|
||||
assertEquals(msgSize, receiveFrame.getBody().length());
|
||||
}
|
||||
|
||||
// remove susbcription
|
||||
ClientStompFrame unsubFrame = connV12.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV12.sendFrame(unsubFrame);
|
||||
|
||||
connV12.disconnect();
|
||||
}
|
||||
|
||||
//core sender -> large (compressed regular) -> stomp v10 receiver
|
||||
@Test
|
||||
public void testReceiveLargeCompressedToRegularPersistentMessagesFromCore() throws Exception {
|
||||
StompClientConnection conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
|
||||
conn.connect(defUser, defPass);
|
||||
|
||||
LargeMessageTestBase.TestLargeMessageInputStream input = new LargeMessageTestBase.TestLargeMessageInputStream(ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, true);
|
||||
LargeMessageTestBase.adjustLargeCompression(true, input, ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
|
||||
|
||||
char[] contents = input.toArray();
|
||||
String msg = new String(contents);
|
||||
|
||||
String leadingPart = msg.substring(0, 100);
|
||||
|
||||
int count = 10;
|
||||
for (int i = 0; i < count; i++) {
|
||||
this.sendJmsMessage(msg);
|
||||
}
|
||||
|
||||
ClientStompFrame subFrame = conn.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("subscription-type", "ANYCAST");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
conn.sendFrame(subFrame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame receiveFrame = conn.receiveFrame(30000);
|
||||
Assert.assertNotNull(receiveFrame);
|
||||
System.out.println("part of frame: " + receiveFrame.getBody().substring(0, 250));
|
||||
Assert.assertTrue(receiveFrame.getCommand().equals("MESSAGE"));
|
||||
Assert.assertEquals(receiveFrame.getHeader("destination"), getQueuePrefix() + getQueueName());
|
||||
int index = receiveFrame.getBody().indexOf(leadingPart);
|
||||
assertEquals(msg.length(), (receiveFrame.getBody().length() - index));
|
||||
}
|
||||
|
||||
// remove suscription
|
||||
ClientStompFrame unsubFrame = conn.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
unsubFrame.addHeader("receipt", "567");
|
||||
ClientStompFrame response = conn.sendFrame(unsubFrame);
|
||||
assertNotNull(response);
|
||||
assertNotNull(response.getCommand().equals("RECEIPT"));
|
||||
|
||||
conn.disconnect();
|
||||
}
|
||||
|
||||
//core sender -> large (compressed regular) -> stomp v12 receiver
|
||||
@Test
|
||||
public void testReceiveLargeCompressedToRegularPersistentMessagesFromCoreV12() throws Exception {
|
||||
LargeMessageTestBase.TestLargeMessageInputStream input = new LargeMessageTestBase.TestLargeMessageInputStream(ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, true);
|
||||
LargeMessageTestBase.adjustLargeCompression(true, input, ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
|
||||
|
||||
char[] contents = input.toArray();
|
||||
String msg = new String(contents);
|
||||
|
||||
int count = 10;
|
||||
for (int i = 0; i < count; i++) {
|
||||
this.sendJmsMessage(msg);
|
||||
}
|
||||
|
||||
StompClientConnection connV12 = StompClientConnectionFactory.createClientConnection("1.2", "localhost", port);
|
||||
connV12.connect(defUser, defPass);
|
||||
|
||||
ClientStompFrame subFrame = connV12.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("subscription-type", "ANYCAST");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
|
||||
connV12.sendFrame(subFrame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame receiveFrame = connV12.receiveFrame(30000);
|
||||
|
||||
Assert.assertNotNull(receiveFrame);
|
||||
System.out.println("part of frame: " + receiveFrame.getBody().substring(0, 20));
|
||||
Assert.assertTrue(receiveFrame.getCommand().equals("MESSAGE"));
|
||||
Assert.assertEquals(receiveFrame.getHeader("destination"), getQueuePrefix() + getQueueName());
|
||||
assertEquals(contents.length, receiveFrame.getBody().length());
|
||||
}
|
||||
|
||||
// remove susbcription
|
||||
ClientStompFrame unsubFrame = connV12.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV12.sendFrame(unsubFrame);
|
||||
|
||||
connV12.disconnect();
|
||||
}
|
||||
|
||||
//core sender -> large (compressed large) -> stomp v12 receiver
|
||||
@Test
|
||||
public void testReceiveLargeCompressedToLargePersistentMessagesFromCoreV12() throws Exception {
|
||||
LargeMessageTestBase.TestLargeMessageInputStream input = new LargeMessageTestBase.TestLargeMessageInputStream(ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, true);
|
||||
input.setSize(10 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
|
||||
LargeMessageTestBase.adjustLargeCompression(false, input, 10 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
|
||||
|
||||
char[] contents = input.toArray();
|
||||
String msg = new String(contents);
|
||||
|
||||
int count = 10;
|
||||
for (int i = 0; i < count; i++) {
|
||||
this.sendJmsMessage(msg);
|
||||
}
|
||||
|
||||
IntegrationTestLogger.LOGGER.info("Message count for " + getQueueName() + ": " + server.getActiveMQServer().locateQueue(SimpleString.toSimpleString(getQueueName())).getMessageCount());
|
||||
|
||||
StompClientConnection connV12 = StompClientConnectionFactory.createClientConnection("1.2", hostname, port);
|
||||
connV12.connect(defUser, defPass);
|
||||
|
||||
ClientStompFrame subFrame = connV12.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("subscription-type", "ANYCAST");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
|
||||
connV12.sendFrame(subFrame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame receiveFrame = connV12.receiveFrame(30000);
|
||||
|
||||
Assert.assertNotNull(receiveFrame);
|
||||
System.out.println("part of frame: " + receiveFrame.getBody().substring(0, 20));
|
||||
Assert.assertTrue(receiveFrame.getCommand().equals("MESSAGE"));
|
||||
Assert.assertEquals(receiveFrame.getHeader("destination"), getQueuePrefix() + getQueueName());
|
||||
assertEquals(contents.length, receiveFrame.getBody().length());
|
||||
}
|
||||
|
||||
// remove susbcription
|
||||
ClientStompFrame unsubFrame = connV12.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV12.sendFrame(unsubFrame);
|
||||
|
||||
connV12.disconnect();
|
||||
}
|
||||
|
||||
//core sender -> large (compressed large) -> stomp v10 receiver
|
||||
@Test
|
||||
public void testReceiveLargeCompressedToLargePersistentMessagesFromCore() throws Exception {
|
||||
LargeMessageTestBase.TestLargeMessageInputStream input = new LargeMessageTestBase.TestLargeMessageInputStream(ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, true);
|
||||
input.setSize(10 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
|
||||
LargeMessageTestBase.adjustLargeCompression(false, input, 10 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
|
||||
|
||||
char[] contents = input.toArray();
|
||||
String msg = new String(contents);
|
||||
|
||||
String leadingPart = msg.substring(0, 100);
|
||||
|
||||
int count = 10;
|
||||
for (int i = 0; i < count; i++) {
|
||||
this.sendJmsMessage(msg);
|
||||
}
|
||||
|
||||
StompClientConnection conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
|
||||
conn.connect(defUser, defPass);
|
||||
|
||||
ClientStompFrame subFrame = conn.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("subscription-type", "ANYCAST");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
conn.sendFrame(subFrame);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ClientStompFrame frame = conn.receiveFrame(60000);
|
||||
Assert.assertNotNull(frame);
|
||||
System.out.println("part of frame: " + frame.getBody().substring(0, 250));
|
||||
Assert.assertTrue(frame.getCommand().equals("MESSAGE"));
|
||||
Assert.assertTrue(frame.getHeader("destination").equals(getQueuePrefix() + getQueueName()));
|
||||
int index = frame.getBody().toString().indexOf(leadingPart);
|
||||
assertEquals(msg.length(), (frame.getBody().toString().length() - index));
|
||||
}
|
||||
|
||||
ClientStompFrame unsubFrame = conn.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
unsubFrame.addHeader("receipt", "567");
|
||||
conn.sendFrame(unsubFrame);
|
||||
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* 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.tests.integration.stomp;
|
||||
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.QueueBrowser;
|
||||
import javax.jms.TextMessage;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnection;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnectionFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class StompTestWithMessageID extends StompTestBase {
|
||||
|
||||
@Override
|
||||
public boolean isEnableStompMessageId() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnableMessageID() throws Exception {
|
||||
StompClientConnection conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
|
||||
conn.connect(defUser, defPass);
|
||||
|
||||
ClientStompFrame frame = conn.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.setBody("Hello World 1");
|
||||
conn.sendFrame(frame);
|
||||
|
||||
frame = conn.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.setBody("Hello World 2");
|
||||
conn.sendFrame(frame);
|
||||
|
||||
QueueBrowser browser = session.createBrowser(queue);
|
||||
|
||||
Enumeration enu = browser.getEnumeration();
|
||||
|
||||
while (enu.hasMoreElements()) {
|
||||
Message msg = (Message) enu.nextElement();
|
||||
String msgId = msg.getStringProperty("amqMessageId");
|
||||
assertNotNull(msgId);
|
||||
assertTrue(msgId.indexOf("STOMP") == 0);
|
||||
}
|
||||
|
||||
browser.close();
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
|
||||
TextMessage message = (TextMessage) consumer.receive(1000);
|
||||
Assert.assertNotNull(message);
|
||||
|
||||
message = (TextMessage) consumer.receive(1000);
|
||||
Assert.assertNotNull(message);
|
||||
|
||||
message = (TextMessage) consumer.receive(2000);
|
||||
Assert.assertNull(message);
|
||||
}
|
||||
}
|
|
@ -19,27 +19,34 @@ package org.apache.activemq.artemis.tests.integration.stomp;
|
|||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnection;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnectionFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class StompTestWithSecurity extends StompTestBase {
|
||||
|
||||
@Override
|
||||
public boolean isSecurityEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJMSXUserID() throws Exception {
|
||||
server.getActiveMQServer().getConfiguration().setPopulateValidatedUser(true);
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
|
||||
String frame = "CONNECT\n" + "login: brianm\n" + "passcode: wombats\n\n" + Stomp.NULL;
|
||||
sendFrame(frame);
|
||||
StompClientConnection conn = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
|
||||
conn.connect(defUser, defPass);
|
||||
|
||||
frame = receiveFrame(10000);
|
||||
Assert.assertTrue(frame.startsWith("CONNECTED"));
|
||||
ClientStompFrame frame = conn.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.setBody("Hello World");
|
||||
conn.sendFrame(frame);
|
||||
|
||||
frame = "SEND\n" + "destination:" + getQueuePrefix() + getQueueName() + "\n\n" + "Hello World" + Stomp.NULL;
|
||||
|
||||
sendFrame(frame);
|
||||
conn.disconnect();
|
||||
|
||||
TextMessage message = (TextMessage) consumer.receive(1000);
|
||||
Assert.assertNotNull(message);
|
||||
|
@ -54,9 +61,4 @@ public class StompTestWithSecurity extends StompTestBase {
|
|||
long tmsg = message.getJMSTimestamp();
|
||||
Assert.assertTrue(Math.abs(tnow - tmsg) < 1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecurityEnabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class AbstractClientStompFrame implements ClientStompFrame {
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
|
||||
|
||||
protected static final String HEADER_RECEIPT = "receipt";
|
||||
public abstract class AbstractClientStompFrame implements ClientStompFrame {
|
||||
|
||||
protected static final Set<String> validCommands = new HashSet<>();
|
||||
protected String command;
|
||||
|
@ -36,19 +36,19 @@ public abstract class AbstractClientStompFrame implements ClientStompFrame {
|
|||
protected String EOL = "\n";
|
||||
|
||||
static {
|
||||
validCommands.add("CONNECT");
|
||||
validCommands.add("CONNECTED");
|
||||
validCommands.add("SEND");
|
||||
validCommands.add("RECEIPT");
|
||||
validCommands.add("SUBSCRIBE");
|
||||
validCommands.add("UNSUBSCRIBE");
|
||||
validCommands.add("MESSAGE");
|
||||
validCommands.add("BEGIN");
|
||||
validCommands.add("COMMIT");
|
||||
validCommands.add("ABORT");
|
||||
validCommands.add("ACK");
|
||||
validCommands.add("DISCONNECT");
|
||||
validCommands.add("ERROR");
|
||||
validCommands.add(Stomp.Commands.CONNECT);
|
||||
validCommands.add(Stomp.Responses.CONNECTED);
|
||||
validCommands.add(Stomp.Commands.SEND);
|
||||
validCommands.add(Stomp.Responses.RECEIPT);
|
||||
validCommands.add(Stomp.Commands.SUBSCRIBE);
|
||||
validCommands.add(Stomp.Commands.UNSUBSCRIBE);
|
||||
validCommands.add(Stomp.Responses.MESSAGE);
|
||||
validCommands.add(Stomp.Commands.BEGIN);
|
||||
validCommands.add(Stomp.Commands.COMMIT);
|
||||
validCommands.add(Stomp.Commands.ABORT);
|
||||
validCommands.add(Stomp.Commands.ACK);
|
||||
validCommands.add(Stomp.Commands.DISCONNECT);
|
||||
validCommands.add(Stomp.Responses.ERROR);
|
||||
}
|
||||
|
||||
public AbstractClientStompFrame(String command) {
|
||||
|
@ -80,37 +80,15 @@ public abstract class AbstractClientStompFrame implements ClientStompFrame {
|
|||
|
||||
@Override
|
||||
public ByteBuffer toByteBuffer() {
|
||||
if (isPing()) {
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(1);
|
||||
buffer.put((byte) 0x0A);
|
||||
buffer.rewind();
|
||||
return buffer;
|
||||
}
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(command + EOL);
|
||||
int n = headers.size();
|
||||
for (int i = 0; i < n; i++) {
|
||||
sb.append(headers.get(i).key + ":" + headers.get(i).val + EOL);
|
||||
}
|
||||
sb.append(EOL);
|
||||
if (body != null) {
|
||||
sb.append(body);
|
||||
}
|
||||
sb.append((char) 0);
|
||||
|
||||
String data = sb.toString();
|
||||
|
||||
byte[] byteValue = data.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(byteValue.length);
|
||||
buffer.put(byteValue);
|
||||
|
||||
buffer.rewind();
|
||||
return buffer;
|
||||
return toByteBufferInternal(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer toByteBufferWithExtra(String str) {
|
||||
return toByteBufferInternal(str);
|
||||
}
|
||||
|
||||
public ByteBuffer toByteBufferInternal(String str) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(command + EOL);
|
||||
int n = headers.size();
|
||||
|
@ -122,7 +100,9 @@ public abstract class AbstractClientStompFrame implements ClientStompFrame {
|
|||
sb.append(body);
|
||||
}
|
||||
sb.append((char) 0);
|
||||
sb.append(str);
|
||||
if (str != null) {
|
||||
sb.append(str);
|
||||
}
|
||||
|
||||
String data = sb.toString();
|
||||
|
||||
|
@ -137,26 +117,29 @@ public abstract class AbstractClientStompFrame implements ClientStompFrame {
|
|||
|
||||
@Override
|
||||
public boolean needsReply() {
|
||||
if ("CONNECT".equals(command) || headerKeys.contains(HEADER_RECEIPT)) {
|
||||
if (Stomp.Commands.CONNECT.equals(command) || headerKeys.contains(Stomp.Headers.RECEIPT_REQUESTED)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCommand(String command) {
|
||||
public ClientStompFrame setCommand(String command) {
|
||||
this.command = command;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(String key, String val) {
|
||||
public ClientStompFrame addHeader(String key, String val) {
|
||||
headers.add(new Header(key, val));
|
||||
headerKeys.add(key);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBody(String body) {
|
||||
public ClientStompFrame setBody(String body) {
|
||||
this.body = body;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -27,29 +27,12 @@ import java.util.concurrent.BlockingQueue;
|
|||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
|
||||
import org.apache.activemq.artemis.tests.integration.IntegrationTestLogger;
|
||||
|
||||
public abstract class AbstractStompClientConnection implements StompClientConnection {
|
||||
|
||||
public static final String STOMP_COMMAND = "STOMP";
|
||||
|
||||
public static final String ACCEPT_HEADER = "accept-version";
|
||||
public static final String HOST_HEADER = "host";
|
||||
public static final String VERSION_HEADER = "version";
|
||||
public static final String RECEIPT_HEADER = "receipt";
|
||||
|
||||
protected static final String CONNECT_COMMAND = "CONNECT";
|
||||
protected static final String CONNECTED_COMMAND = "CONNECTED";
|
||||
protected static final String DISCONNECT_COMMAND = "DISCONNECT";
|
||||
|
||||
protected static final String LOGIN_HEADER = "login";
|
||||
protected static final String PASSCODE_HEADER = "passcode";
|
||||
|
||||
//ext
|
||||
protected static final String CLIENT_ID_HEADER = "client-id";
|
||||
|
||||
protected Pinger pinger;
|
||||
|
||||
protected String version;
|
||||
protected String host;
|
||||
protected int port;
|
||||
|
@ -58,13 +41,10 @@ public abstract class AbstractStompClientConnection implements StompClientConnec
|
|||
protected StompFrameFactory factory;
|
||||
protected final SocketChannel socketChannel;
|
||||
protected ByteBuffer readBuffer;
|
||||
|
||||
protected List<Byte> receiveList;
|
||||
|
||||
protected BlockingQueue<ClientStompFrame> frameQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
protected boolean connected = false;
|
||||
private int serverPingCounter;
|
||||
protected int serverPingCounter;
|
||||
|
||||
public AbstractStompClientConnection(String version, String host, int port) throws IOException {
|
||||
this.version = version;
|
||||
|
@ -90,11 +70,15 @@ public abstract class AbstractStompClientConnection implements StompClientConnec
|
|||
new ReaderThread().start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientStompFrame sendFrame(ClientStompFrame frame) throws IOException, InterruptedException {
|
||||
private ClientStompFrame sendFrameInternal(ClientStompFrame frame, boolean wicked) throws IOException, InterruptedException {
|
||||
ClientStompFrame response = null;
|
||||
IntegrationTestLogger.LOGGER.info("Sending frame:\n" + frame);
|
||||
ByteBuffer buffer = frame.toByteBuffer();
|
||||
IntegrationTestLogger.LOGGER.info("Sending " + (wicked ? "*wicked* " : "") + "frame:\n" + frame);
|
||||
ByteBuffer buffer;
|
||||
if (wicked) {
|
||||
buffer = frame.toByteBufferWithExtra("\n");
|
||||
} else {
|
||||
buffer = frame.toByteBuffer();
|
||||
}
|
||||
while (buffer.remaining() > 0) {
|
||||
socketChannel.write(buffer);
|
||||
}
|
||||
|
@ -105,7 +89,7 @@ public abstract class AbstractStompClientConnection implements StompClientConnec
|
|||
|
||||
//filter out server ping
|
||||
while (response != null) {
|
||||
if (response.getCommand().equals("STOMP")) {
|
||||
if (response.getCommand().equals(Stomp.Commands.STOMP)) {
|
||||
response = receiveFrame();
|
||||
} else {
|
||||
break;
|
||||
|
@ -113,32 +97,19 @@ public abstract class AbstractStompClientConnection implements StompClientConnec
|
|||
}
|
||||
}
|
||||
|
||||
IntegrationTestLogger.LOGGER.info("Received:\n" + response);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientStompFrame sendFrame(ClientStompFrame frame) throws IOException, InterruptedException {
|
||||
return sendFrameInternal(frame, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientStompFrame sendWickedFrame(ClientStompFrame frame) throws IOException, InterruptedException {
|
||||
ClientStompFrame response = null;
|
||||
ByteBuffer buffer = frame.toByteBufferWithExtra("\n");
|
||||
|
||||
while (buffer.remaining() > 0) {
|
||||
socketChannel.write(buffer);
|
||||
}
|
||||
|
||||
//now response
|
||||
if (frame.needsReply()) {
|
||||
response = receiveFrame();
|
||||
|
||||
//filter out server ping
|
||||
while (response != null) {
|
||||
if (response.getCommand().equals("STOMP")) {
|
||||
response = receiveFrame();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return response;
|
||||
return sendFrameInternal(frame, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -186,17 +157,12 @@ public abstract class AbstractStompClientConnection implements StompClientConnec
|
|||
readBuffer.rewind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServerPingNumber() {
|
||||
return serverPingCounter;
|
||||
}
|
||||
|
||||
protected void incrementServerPing() {
|
||||
serverPingCounter++;
|
||||
}
|
||||
|
||||
private boolean validateFrame(ClientStompFrame f) {
|
||||
String h = f.getHeader("content-length");
|
||||
String h = f.getHeader(Stomp.Headers.CONTENT_LENGTH);
|
||||
if (h != null) {
|
||||
int len = Integer.valueOf(h);
|
||||
if (f.getBody().getBytes(StandardCharsets.UTF_8).length < len) {
|
||||
|
@ -271,34 +237,15 @@ public abstract class AbstractStompClientConnection implements StompClientConnec
|
|||
return this.frameQueue.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startPinger(long interval) {
|
||||
pinger = new Pinger(interval);
|
||||
pinger.startPing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopPinger() {
|
||||
if (pinger != null) {
|
||||
pinger.stopPing();
|
||||
try {
|
||||
pinger.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
pinger = null;
|
||||
}
|
||||
}
|
||||
|
||||
private class Pinger extends Thread {
|
||||
protected class Pinger extends Thread {
|
||||
|
||||
long pingInterval;
|
||||
ClientStompFrame pingFrame;
|
||||
volatile boolean stop = false;
|
||||
|
||||
private Pinger(long interval) {
|
||||
Pinger(long interval) {
|
||||
this.pingInterval = interval;
|
||||
pingFrame = createFrame("STOMP");
|
||||
pingFrame = createFrame(Stomp.Commands.STOMP);
|
||||
pingFrame.setBody("\n");
|
||||
pingFrame.setForceOneway();
|
||||
pingFrame.setPing(true);
|
||||
|
@ -329,5 +276,4 @@ public abstract class AbstractStompClientConnection implements StompClientConnec
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,11 +27,11 @@ public interface ClientStompFrame {
|
|||
|
||||
boolean needsReply();
|
||||
|
||||
void setCommand(String command);
|
||||
ClientStompFrame setCommand(String command);
|
||||
|
||||
void addHeader(String string, String string2);
|
||||
ClientStompFrame addHeader(String string, String string2);
|
||||
|
||||
void setBody(String string);
|
||||
ClientStompFrame setBody(String string);
|
||||
|
||||
String getCommand();
|
||||
|
||||
|
@ -43,8 +43,8 @@ public interface ClientStompFrame {
|
|||
|
||||
boolean isPing();
|
||||
|
||||
void setForceOneway();
|
||||
ClientStompFrame setForceOneway();
|
||||
|
||||
void setPing(boolean b);
|
||||
ClientStompFrame setPing(boolean b);
|
||||
|
||||
}
|
||||
|
|
|
@ -29,19 +29,19 @@ public class ClientStompFrameV10 extends AbstractClientStompFrame {
|
|||
super(command, validate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientStompFrame setForceOneway() {
|
||||
throw new IllegalStateException("Doesn't apply with V1.0!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientStompFrame setPing(boolean b) {
|
||||
throw new IllegalStateException("Doesn't apply with V1.0!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceOneway() {
|
||||
throw new IllegalStateException("Doesn't apply with V1.0!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPing(boolean b) {
|
||||
throw new IllegalStateException("Doesn't apply with V1.0!");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,14 +16,13 @@
|
|||
*/
|
||||
package org.apache.activemq.artemis.tests.integration.stomp.util;
|
||||
|
||||
/**
|
||||
* pls use factory to create frames.
|
||||
*/
|
||||
public class ClientStompFrameV11 extends AbstractClientStompFrame {
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
|
||||
|
||||
public class ClientStompFrameV11 extends ClientStompFrameV10 {
|
||||
|
||||
static {
|
||||
validCommands.add("NACK");
|
||||
validCommands.add("STOMP");
|
||||
validCommands.add(Stomp.Commands.NACK);
|
||||
validCommands.add(Stomp.Commands.STOMP);
|
||||
}
|
||||
|
||||
boolean forceOneway = false;
|
||||
|
@ -38,8 +37,9 @@ public class ClientStompFrameV11 extends AbstractClientStompFrame {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setForceOneway() {
|
||||
public ClientStompFrame setForceOneway() {
|
||||
forceOneway = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -47,15 +47,17 @@ public class ClientStompFrameV11 extends AbstractClientStompFrame {
|
|||
if (forceOneway)
|
||||
return false;
|
||||
|
||||
if ("CONNECT".equals(command) || "STOMP".equals(command) || headerKeys.contains(HEADER_RECEIPT)) {
|
||||
if (Stomp.Commands.STOMP.equals(command)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return super.needsReply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPing(boolean b) {
|
||||
public ClientStompFrame setPing(boolean b) {
|
||||
isPing = b;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,17 +16,7 @@
|
|||
*/
|
||||
package org.apache.activemq.artemis.tests.integration.stomp.util;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class ClientStompFrameV12 extends AbstractClientStompFrame {
|
||||
|
||||
static {
|
||||
validCommands.add("NACK");
|
||||
validCommands.add("STOMP");
|
||||
}
|
||||
|
||||
boolean forceOneway = false;
|
||||
boolean isPing = false;
|
||||
public class ClientStompFrameV12 extends ClientStompFrameV11 {
|
||||
|
||||
public ClientStompFrameV12(String command) {
|
||||
this(command, true, true);
|
||||
|
@ -44,32 +34,6 @@ public class ClientStompFrameV12 extends AbstractClientStompFrame {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceOneway() {
|
||||
forceOneway = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsReply() {
|
||||
if (forceOneway)
|
||||
return false;
|
||||
|
||||
if ("CONNECT".equals(command) || "STOMP".equals(command) || headerKeys.contains(HEADER_RECEIPT)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPing(boolean b) {
|
||||
isPing = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPing() {
|
||||
return isPing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[1.2]" + super.toString();
|
||||
|
|
|
@ -18,9 +18,6 @@ package org.apache.activemq.artemis.tests.integration.stomp.util;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* pls use factory to create frames.
|
||||
*/
|
||||
public interface StompClientConnection {
|
||||
|
||||
ClientStompFrame sendFrame(ClientStompFrame frame) throws IOException, InterruptedException;
|
||||
|
@ -35,7 +32,7 @@ public interface StompClientConnection {
|
|||
|
||||
ClientStompFrame connect(String defUser, String defPass) throws Exception;
|
||||
|
||||
void connect(String defUser, String defPass, String clientId) throws Exception;
|
||||
ClientStompFrame connect(String defUser, String defPass, String clientId) throws Exception;
|
||||
|
||||
boolean isConnected();
|
||||
|
||||
|
|
|
@ -18,52 +18,47 @@ package org.apache.activemq.artemis.tests.integration.stomp.util;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* pls use factory to create frames.
|
||||
*/
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
|
||||
import org.apache.activemq.artemis.tests.integration.IntegrationTestLogger;
|
||||
|
||||
public class StompClientConnectionV10 extends AbstractStompClientConnection {
|
||||
|
||||
public StompClientConnectionV10(String host, int port) throws IOException {
|
||||
super("1.0", host, port);
|
||||
}
|
||||
|
||||
public StompClientConnectionV10(String version, String host, int port) throws IOException {
|
||||
super(version, host, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientStompFrame connect(String username, String passcode) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = factory.newFrame(CONNECT_COMMAND);
|
||||
frame.addHeader(LOGIN_HEADER, username);
|
||||
frame.addHeader(PASSCODE_HEADER, passcode);
|
||||
return connect(username, passcode, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientStompFrame connect(String username, String passcode, String clientID) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = factory.newFrame(Stomp.Commands.CONNECT);
|
||||
frame.addHeader(Stomp.Headers.Connect.LOGIN, username);
|
||||
frame.addHeader(Stomp.Headers.Connect.PASSCODE, passcode);
|
||||
if (clientID != null) {
|
||||
frame.addHeader(Stomp.Headers.Connect.CLIENT_ID, clientID);
|
||||
}
|
||||
|
||||
ClientStompFrame response = this.sendFrame(frame);
|
||||
|
||||
if (response.getCommand().equals(CONNECTED_COMMAND)) {
|
||||
if (response.getCommand().equals(Stomp.Responses.CONNECTED)) {
|
||||
connected = true;
|
||||
} else {
|
||||
System.out.println("Connection failed with: " + response);
|
||||
IntegrationTestLogger.LOGGER.warn("Connection failed with: " + response);
|
||||
connected = false;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(String username, String passcode, String clientID) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = factory.newFrame(CONNECT_COMMAND);
|
||||
frame.addHeader(LOGIN_HEADER, username);
|
||||
frame.addHeader(PASSCODE_HEADER, passcode);
|
||||
frame.addHeader(CLIENT_ID_HEADER, clientID);
|
||||
|
||||
ClientStompFrame response = this.sendFrame(frame);
|
||||
|
||||
if (response.getCommand().equals(CONNECTED_COMMAND)) {
|
||||
connected = true;
|
||||
} else {
|
||||
System.out.println("Connection failed with: " + response);
|
||||
connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = factory.newFrame(DISCONNECT_COMMAND);
|
||||
ClientStompFrame frame = factory.newFrame(Stomp.Commands.DISCONNECT);
|
||||
this.sendFrame(frame);
|
||||
|
||||
close();
|
||||
|
|
|
@ -17,28 +17,40 @@
|
|||
package org.apache.activemq.artemis.tests.integration.stomp.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class StompClientConnectionV11 extends AbstractStompClientConnection {
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
|
||||
|
||||
public class StompClientConnectionV11 extends StompClientConnectionV10 {
|
||||
|
||||
public StompClientConnectionV11(String host, int port) throws IOException {
|
||||
super("1.1", host, port);
|
||||
}
|
||||
|
||||
public StompClientConnectionV11(String version, String host, int port) throws IOException {
|
||||
super(version, host, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientStompFrame connect(String username, String passcode) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = factory.newFrame(CONNECT_COMMAND);
|
||||
frame.addHeader(ACCEPT_HEADER, "1.1");
|
||||
frame.addHeader(HOST_HEADER, "localhost");
|
||||
public ClientStompFrame connect(String username, String passcode, String clientID) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = factory.newFrame(Stomp.Commands.CONNECT);
|
||||
frame.addHeader(Stomp.Headers.Connect.ACCEPT_VERSION, getVersion());
|
||||
frame.addHeader(Stomp.Headers.Connect.HOST, "localhost");
|
||||
if (clientID != null) {
|
||||
frame.addHeader(Stomp.Headers.Connect.CLIENT_ID, clientID);
|
||||
}
|
||||
|
||||
if (username != null) {
|
||||
frame.addHeader(LOGIN_HEADER, username);
|
||||
frame.addHeader(PASSCODE_HEADER, passcode);
|
||||
frame.addHeader(Stomp.Headers.Connect.LOGIN, username);
|
||||
frame.addHeader(Stomp.Headers.Connect.PASSCODE, passcode);
|
||||
}
|
||||
|
||||
ClientStompFrame response = this.sendFrame(frame);
|
||||
|
||||
if (response.getCommand().equals(CONNECTED_COMMAND)) {
|
||||
String version = response.getHeader(VERSION_HEADER);
|
||||
assert (version.equals("1.1"));
|
||||
if (Stomp.Responses.CONNECTED.equals(response.getCommand())) {
|
||||
String version = response.getHeader(Stomp.Headers.Connected.VERSION);
|
||||
if (!version.equals(getVersion()))
|
||||
throw new IllegalStateException("incorrect version!");
|
||||
|
||||
this.username = username;
|
||||
this.passcode = passcode;
|
||||
|
@ -49,46 +61,21 @@ public class StompClientConnectionV11 extends AbstractStompClientConnection {
|
|||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(String username, String passcode, String clientID) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = factory.newFrame(CONNECT_COMMAND);
|
||||
frame.addHeader(ACCEPT_HEADER, "1.1");
|
||||
frame.addHeader(HOST_HEADER, "localhost");
|
||||
frame.addHeader(CLIENT_ID_HEADER, clientID);
|
||||
|
||||
if (username != null) {
|
||||
frame.addHeader(LOGIN_HEADER, username);
|
||||
frame.addHeader(PASSCODE_HEADER, passcode);
|
||||
}
|
||||
|
||||
ClientStompFrame response = this.sendFrame(frame);
|
||||
|
||||
if (response.getCommand().equals(CONNECTED_COMMAND)) {
|
||||
String version = response.getHeader(VERSION_HEADER);
|
||||
assert (version.equals("1.1"));
|
||||
|
||||
this.username = username;
|
||||
this.passcode = passcode;
|
||||
this.connected = true;
|
||||
} else {
|
||||
connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void connect1(String username, String passcode) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = factory.newFrame(STOMP_COMMAND);
|
||||
frame.addHeader(ACCEPT_HEADER, "1.0,1.1");
|
||||
frame.addHeader(HOST_HEADER, "127.0.0.1");
|
||||
ClientStompFrame frame = factory.newFrame(Stomp.Commands.STOMP);
|
||||
frame.addHeader(Stomp.Headers.Connect.ACCEPT_VERSION, "1.0,1.1");
|
||||
frame.addHeader(Stomp.Headers.Connect.HOST, "127.0.0.1");
|
||||
if (username != null) {
|
||||
frame.addHeader(LOGIN_HEADER, username);
|
||||
frame.addHeader(PASSCODE_HEADER, passcode);
|
||||
frame.addHeader(Stomp.Headers.Connect.LOGIN, username);
|
||||
frame.addHeader(Stomp.Headers.Connect.PASSCODE, passcode);
|
||||
}
|
||||
|
||||
ClientStompFrame response = this.sendFrame(frame);
|
||||
|
||||
if (response.getCommand().equals(CONNECTED_COMMAND)) {
|
||||
String version = response.getHeader(VERSION_HEADER);
|
||||
assert (version.equals("1.1"));
|
||||
if (Stomp.Responses.CONNECTED.equals(response.getCommand())) {
|
||||
String version = response.getHeader(Stomp.Headers.Connected.VERSION);
|
||||
if (!version.equals(getVersion()))
|
||||
throw new IllegalStateException("incorrect version!");
|
||||
|
||||
this.username = username;
|
||||
this.passcode = passcode;
|
||||
|
@ -103,12 +90,15 @@ public class StompClientConnectionV11 extends AbstractStompClientConnection {
|
|||
public void disconnect() throws IOException, InterruptedException {
|
||||
stopPinger();
|
||||
|
||||
ClientStompFrame frame = factory.newFrame(DISCONNECT_COMMAND);
|
||||
frame.addHeader("receipt", "1");
|
||||
ClientStompFrame frame = factory.newFrame(Stomp.Commands.DISCONNECT);
|
||||
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
|
||||
frame.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
|
||||
|
||||
ClientStompFrame result = this.sendFrame(frame);
|
||||
|
||||
if (result == null || (!"RECEIPT".equals(result.getCommand())) || (!"1".equals(result.getHeader("receipt-id")))) {
|
||||
if (result == null || (!Stomp.Responses.RECEIPT.equals(result.getCommand())) || (!uuid.equals(result.getHeader(Stomp.Headers.Response.RECEIPT_ID)))) {
|
||||
throw new IOException("Disconnect failed! " + result);
|
||||
}
|
||||
|
||||
|
@ -122,4 +112,28 @@ public class StompClientConnectionV11 extends AbstractStompClientConnection {
|
|||
return factory.newFrame(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startPinger(long interval) {
|
||||
pinger = new Pinger(interval);
|
||||
pinger.startPing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopPinger() {
|
||||
if (pinger != null) {
|
||||
pinger.stopPing();
|
||||
try {
|
||||
pinger.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
pinger = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServerPingNumber() {
|
||||
return serverPingCounter;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,90 +18,13 @@ package org.apache.activemq.artemis.tests.integration.stomp.util;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
public class StompClientConnectionV12 extends AbstractStompClientConnection {
|
||||
public class StompClientConnectionV12 extends StompClientConnectionV11 {
|
||||
|
||||
public StompClientConnectionV12(String host, int port) throws IOException {
|
||||
super("1.2", host, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientStompFrame createFrame(String command) {
|
||||
return factory.newFrame(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientStompFrame connect(String username, String passcode) throws IOException, InterruptedException {
|
||||
ClientStompFrame frame = factory.newFrame(CONNECT_COMMAND);
|
||||
frame.addHeader(ACCEPT_HEADER, "1.2");
|
||||
frame.addHeader(HOST_HEADER, "localhost");
|
||||
if (username != null) {
|
||||
frame.addHeader(LOGIN_HEADER, username);
|
||||
frame.addHeader(PASSCODE_HEADER, passcode);
|
||||
}
|
||||
|
||||
ClientStompFrame response = this.sendFrame(frame);
|
||||
|
||||
if (response.getCommand().equals(CONNECTED_COMMAND)) {
|
||||
String version = response.getHeader(VERSION_HEADER);
|
||||
if (!version.equals("1.2"))
|
||||
throw new IllegalStateException("incorrect version!");
|
||||
|
||||
this.username = username;
|
||||
this.passcode = passcode;
|
||||
this.connected = true;
|
||||
} else {
|
||||
connected = false;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() throws IOException, InterruptedException {
|
||||
stopPinger();
|
||||
|
||||
ClientStompFrame frame = factory.newFrame(DISCONNECT_COMMAND);
|
||||
frame.addHeader("receipt", "1");
|
||||
|
||||
ClientStompFrame result = this.sendFrame(frame);
|
||||
|
||||
if (result == null || (!"RECEIPT".equals(result.getCommand())) || (!"1".equals(result.getHeader("receipt-id")))) {
|
||||
throw new IOException("Disconnect failed! " + result);
|
||||
}
|
||||
|
||||
close();
|
||||
|
||||
connected = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(String username, String passcode, String clientID) throws Exception {
|
||||
ClientStompFrame frame = factory.newFrame(CONNECT_COMMAND);
|
||||
frame.addHeader(ACCEPT_HEADER, "1.2");
|
||||
frame.addHeader(HOST_HEADER, "localhost");
|
||||
frame.addHeader(CLIENT_ID_HEADER, clientID);
|
||||
|
||||
if (username != null) {
|
||||
frame.addHeader(LOGIN_HEADER, username);
|
||||
frame.addHeader(PASSCODE_HEADER, passcode);
|
||||
}
|
||||
|
||||
ClientStompFrame response = this.sendFrame(frame);
|
||||
|
||||
if (response.getCommand().equals(CONNECTED_COMMAND)) {
|
||||
String version = response.getHeader(VERSION_HEADER);
|
||||
if (!version.equals("1.2"))
|
||||
throw new IllegalStateException("incorrect version!");
|
||||
|
||||
this.username = username;
|
||||
this.passcode = passcode;
|
||||
this.connected = true;
|
||||
} else {
|
||||
connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
public ClientStompFrame createAnyFrame(String command) {
|
||||
return factory.newAnyFrame(command);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,4 +24,6 @@ public interface StompFrameFactory {
|
|||
|
||||
ClientStompFrame newAnyFrame(String command);
|
||||
|
||||
String[] handleHeaders(String header);
|
||||
|
||||
}
|
||||
|
|
|
@ -38,18 +38,18 @@ import java.util.StringTokenizer;
|
|||
public class StompFrameFactoryV10 implements StompFrameFactory {
|
||||
|
||||
@Override
|
||||
public ClientStompFrame createFrame(String data) {
|
||||
public ClientStompFrame createFrame(final String data) {
|
||||
//split the string at "\n\n"
|
||||
String[] dataFields = data.split("\n\n");
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(dataFields[0], "\n");
|
||||
|
||||
String command = tokenizer.nextToken();
|
||||
ClientStompFrame frame = new ClientStompFrameV10(command);
|
||||
ClientStompFrame frame = newFrame(command);
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
String header = tokenizer.nextToken();
|
||||
String[] fields = header.split(":");
|
||||
String[] fields = handleHeaders(header);
|
||||
frame.addHeader(fields[0], fields[1]);
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,11 @@ public class StompFrameFactoryV10 implements StompFrameFactory {
|
|||
return frame;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] handleHeaders(String header) {
|
||||
return header.split(":");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientStompFrame newFrame(String command) {
|
||||
return new ClientStompFrameV10(command);
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
*/
|
||||
package org.apache.activemq.artemis.tests.integration.stomp.util;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* 1.1 frames
|
||||
* <br>
|
||||
|
@ -36,32 +34,10 @@ import java.util.StringTokenizer;
|
|||
* 13. RECEIPT
|
||||
* 14. ERROR
|
||||
*/
|
||||
public class StompFrameFactoryV11 implements StompFrameFactory {
|
||||
public class StompFrameFactoryV11 extends StompFrameFactoryV10 {
|
||||
|
||||
@Override
|
||||
public ClientStompFrame createFrame(final String data) {
|
||||
//split the string at "\n\n"
|
||||
String[] dataFields = data.split("\n\n");
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(dataFields[0], "\n");
|
||||
|
||||
String command = tokenizer.nextToken();
|
||||
ClientStompFrame frame = new ClientStompFrameV11(command);
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
String header = tokenizer.nextToken();
|
||||
String[] fields = splitAndDecodeHeader(header);
|
||||
frame.addHeader(fields[0], fields[1]);
|
||||
}
|
||||
|
||||
//body (without null byte)
|
||||
if (dataFields.length == 2) {
|
||||
frame.setBody(dataFields[1]);
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
private String[] splitAndDecodeHeader(String header) {
|
||||
public String[] handleHeaders(String header) {
|
||||
// split the header into the key and value at the ":" since there shouldn't be any unescaped colons in the header
|
||||
// except for the one separating the key and value
|
||||
String[] result = header.split(":");
|
||||
|
|
|
@ -16,44 +16,10 @@
|
|||
*/
|
||||
package org.apache.activemq.artemis.tests.integration.stomp.util;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class StompFrameFactoryV12 implements StompFrameFactory {
|
||||
public class StompFrameFactoryV12 extends StompFrameFactoryV11 {
|
||||
|
||||
@Override
|
||||
public ClientStompFrame createFrame(String data) {
|
||||
//split the string at "\n\n"
|
||||
String[] dataFields = data.split("\n\n");
|
||||
|
||||
StringTokenizer tokenizer = new StringTokenizer(dataFields[0], "\n");
|
||||
|
||||
String command = tokenizer.nextToken();
|
||||
ClientStompFrame frame = new ClientStompFrameV12(command);
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
String header = tokenizer.nextToken();
|
||||
String[] fields = splitAndDecodeHeader(header);
|
||||
frame.addHeader(fields[0], fields[1]);
|
||||
}
|
||||
|
||||
//body (without null byte)
|
||||
if (dataFields.length == 2) {
|
||||
frame.setBody(dataFields[1]);
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
public void printByteHeader(String headers) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
for (int i = 0; i < headers.length(); i++) {
|
||||
char c = headers.charAt(i);
|
||||
buffer.append((byte) c + " ");
|
||||
}
|
||||
System.out.println("header in byte : " + buffer.toString());
|
||||
}
|
||||
|
||||
private String[] splitAndDecodeHeader(String header) {
|
||||
public String[] handleHeaders(String header) {
|
||||
// split the header into the key and value at the ":" since there shouldn't be any unescaped colons in the header
|
||||
// except for the one separating the key and value
|
||||
String[] result = header.split(":");
|
||||
|
|
|
@ -18,6 +18,8 @@ package org.apache.activemq.artemis.tests.integration.stomp.v11;
|
|||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.StompTestBase;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnection;
|
||||
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnectionFactory;
|
||||
|
@ -28,15 +30,19 @@ import org.junit.Test;
|
|||
/*
|
||||
* Some Stomp tests against server with persistence enabled are put here.
|
||||
*/
|
||||
public class ExtraStompTest extends StompV11TestBase {
|
||||
public class ExtraStompTest extends StompTestBase {
|
||||
|
||||
private StompClientConnection connV10;
|
||||
private StompClientConnection connV11;
|
||||
|
||||
@Override
|
||||
public boolean isPersistenceEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
persistenceEnabled = true;
|
||||
super.setUp();
|
||||
connV10 = StompClientConnectionFactory.createClientConnection("1.0", hostname, port);
|
||||
connV10.connect(defUser, defPass);
|
||||
|
@ -57,331 +63,142 @@ public class ExtraStompTest extends StompV11TestBase {
|
|||
|
||||
@Test
|
||||
public void testSendAndReceive10() throws Exception {
|
||||
String msg1 = "Hello World 1!";
|
||||
String msg2 = "Hello World 2!";
|
||||
|
||||
ClientStompFrame frame = connV10.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("content-length", String.valueOf(msg1.getBytes(StandardCharsets.UTF_8).length));
|
||||
frame.addHeader("persistent", "true");
|
||||
frame.setBody(msg1);
|
||||
|
||||
connV10.sendFrame(frame);
|
||||
|
||||
ClientStompFrame frame2 = connV10.createFrame("SEND");
|
||||
frame2.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame2.addHeader("content-length", String.valueOf(msg2.getBytes(StandardCharsets.UTF_8).length));
|
||||
frame2.addHeader("persistent", "true");
|
||||
frame2.setBody(msg2);
|
||||
|
||||
connV10.sendFrame(frame2);
|
||||
|
||||
ClientStompFrame subFrame = connV10.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
|
||||
connV10.sendFrame(subFrame);
|
||||
|
||||
frame = connV10.receiveFrame();
|
||||
|
||||
System.out.println("received " + frame);
|
||||
|
||||
assertEquals("MESSAGE", frame.getCommand());
|
||||
|
||||
assertEquals("a-sub", frame.getHeader("subscription"));
|
||||
|
||||
assertNotNull(frame.getHeader("message-id"));
|
||||
|
||||
assertEquals(getQueuePrefix() + getQueueName(), frame.getHeader("destination"));
|
||||
|
||||
assertEquals(msg1, frame.getBody());
|
||||
|
||||
frame = connV10.receiveFrame();
|
||||
|
||||
System.out.println("received " + frame);
|
||||
|
||||
assertEquals("MESSAGE", frame.getCommand());
|
||||
|
||||
assertEquals("a-sub", frame.getHeader("subscription"));
|
||||
|
||||
assertNotNull(frame.getHeader("message-id"));
|
||||
|
||||
assertEquals(getQueuePrefix() + getQueueName(), frame.getHeader("destination"));
|
||||
|
||||
assertEquals(msg2, frame.getBody());
|
||||
|
||||
//unsub
|
||||
ClientStompFrame unsubFrame = connV10.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV10.sendFrame(unsubFrame);
|
||||
|
||||
testSendAndReceive(connV10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAndReceive11() throws Exception {
|
||||
testSendAndReceive(connV11);
|
||||
}
|
||||
|
||||
public void testSendAndReceive(StompClientConnection conn) throws Exception {
|
||||
String msg1 = "Hello World 1!";
|
||||
String msg2 = "Hello World 2!";
|
||||
|
||||
ClientStompFrame frame = connV11.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("content-length", String.valueOf(msg1.getBytes(StandardCharsets.UTF_8).length));
|
||||
frame.addHeader("persistent", "true");
|
||||
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND);
|
||||
frame.addHeader(Stomp.Headers.Subscribe.DESTINATION, getQueuePrefix() + getQueueName());
|
||||
frame.addHeader(Stomp.Headers.CONTENT_LENGTH, String.valueOf(msg1.getBytes(StandardCharsets.UTF_8).length));
|
||||
frame.addHeader(Stomp.Headers.Send.PERSISTENT, Boolean.TRUE.toString());
|
||||
frame.setBody(msg1);
|
||||
|
||||
connV11.sendFrame(frame);
|
||||
conn.sendFrame(frame);
|
||||
|
||||
ClientStompFrame frame2 = connV11.createFrame("SEND");
|
||||
frame2.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame2.addHeader("content-length", String.valueOf(msg2.getBytes(StandardCharsets.UTF_8).length));
|
||||
frame2.addHeader("persistent", "true");
|
||||
ClientStompFrame frame2 = conn.createFrame(Stomp.Commands.SEND);
|
||||
frame2.addHeader(Stomp.Headers.Subscribe.DESTINATION, getQueuePrefix() + getQueueName());
|
||||
frame2.addHeader(Stomp.Headers.CONTENT_LENGTH, String.valueOf(msg2.getBytes(StandardCharsets.UTF_8).length));
|
||||
frame2.addHeader(Stomp.Headers.Send.PERSISTENT, Boolean.TRUE.toString());
|
||||
frame2.setBody(msg2);
|
||||
|
||||
connV11.sendFrame(frame2);
|
||||
conn.sendFrame(frame2);
|
||||
|
||||
ClientStompFrame subFrame = connV11.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
subscribe(conn, "a-sub");
|
||||
|
||||
connV11.sendFrame(subFrame);
|
||||
|
||||
frame = connV11.receiveFrame();
|
||||
|
||||
System.out.println("received " + frame);
|
||||
|
||||
assertEquals("MESSAGE", frame.getCommand());
|
||||
|
||||
assertEquals("a-sub", frame.getHeader("subscription"));
|
||||
|
||||
assertNotNull(frame.getHeader("message-id"));
|
||||
|
||||
assertEquals(getQueuePrefix() + getQueueName(), frame.getHeader("destination"));
|
||||
frame = conn.receiveFrame();
|
||||
|
||||
assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
|
||||
assertEquals("a-sub", frame.getHeader(Stomp.Headers.Message.SUBSCRIPTION));
|
||||
assertNotNull(frame.getHeader(Stomp.Headers.Message.MESSAGE_ID));
|
||||
assertEquals(getQueuePrefix() + getQueueName(), frame.getHeader(Stomp.Headers.Subscribe.DESTINATION));
|
||||
assertEquals(msg1, frame.getBody());
|
||||
|
||||
frame = connV11.receiveFrame();
|
||||
|
||||
System.out.println("received " + frame);
|
||||
|
||||
assertEquals("MESSAGE", frame.getCommand());
|
||||
|
||||
assertEquals("a-sub", frame.getHeader("subscription"));
|
||||
|
||||
assertNotNull(frame.getHeader("message-id"));
|
||||
|
||||
assertEquals(getQueuePrefix() + getQueueName(), frame.getHeader("destination"));
|
||||
frame = conn.receiveFrame();
|
||||
|
||||
assertEquals(Stomp.Responses.MESSAGE, frame.getCommand());
|
||||
assertEquals("a-sub", frame.getHeader(Stomp.Headers.Message.SUBSCRIPTION));
|
||||
assertNotNull(frame.getHeader(Stomp.Headers.Message.MESSAGE_ID));
|
||||
assertEquals(getQueuePrefix() + getQueueName(), frame.getHeader(Stomp.Headers.Subscribe.DESTINATION));
|
||||
assertEquals(msg2, frame.getBody());
|
||||
|
||||
//unsub
|
||||
ClientStompFrame unsubFrame = connV11.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV11.sendFrame(unsubFrame);
|
||||
unsubscribe(conn, "a-sub");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoGarbageAfterPersistentMessageV10() throws Exception {
|
||||
ClientStompFrame subFrame = connV10.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
|
||||
connV10.sendFrame(subFrame);
|
||||
|
||||
ClientStompFrame frame = connV10.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("content-length", "11");
|
||||
frame.addHeader("persistent", "true");
|
||||
frame.setBody("Hello World");
|
||||
|
||||
connV10.sendFrame(frame);
|
||||
|
||||
frame = connV10.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("content-length", "11");
|
||||
frame.addHeader("persistent", "true");
|
||||
frame.setBody("Hello World");
|
||||
|
||||
connV10.sendFrame(frame);
|
||||
|
||||
frame = connV10.receiveFrame(10000);
|
||||
|
||||
System.out.println("received: " + frame);
|
||||
|
||||
assertEquals("Hello World", frame.getBody());
|
||||
|
||||
//if activemq sends trailing garbage bytes, the second message
|
||||
//will not be normal
|
||||
frame = connV10.receiveFrame(10000);
|
||||
|
||||
System.out.println("received: " + frame);
|
||||
|
||||
assertEquals("Hello World", frame.getBody());
|
||||
|
||||
//unsub
|
||||
ClientStompFrame unsubFrame = connV10.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV10.sendFrame(unsubFrame);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoGarbageOnPersistentRedeliveryV10() throws Exception {
|
||||
|
||||
ClientStompFrame frame = connV10.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("content-length", "11");
|
||||
frame.addHeader("persistent", "true");
|
||||
frame.setBody("Hello World");
|
||||
|
||||
connV10.sendFrame(frame);
|
||||
|
||||
frame = connV10.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("content-length", "11");
|
||||
frame.addHeader("persistent", "true");
|
||||
frame.setBody("Hello World");
|
||||
|
||||
connV10.sendFrame(frame);
|
||||
|
||||
ClientStompFrame subFrame = connV10.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "client");
|
||||
|
||||
connV10.sendFrame(subFrame);
|
||||
|
||||
// receive but don't ack
|
||||
frame = connV10.receiveFrame(10000);
|
||||
frame = connV10.receiveFrame(10000);
|
||||
|
||||
System.out.println("received: " + frame);
|
||||
|
||||
//unsub
|
||||
ClientStompFrame unsubFrame = connV10.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV10.sendFrame(unsubFrame);
|
||||
|
||||
subFrame = connV10.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
|
||||
connV10.sendFrame(subFrame);
|
||||
|
||||
frame = connV10.receiveFrame(10000);
|
||||
frame = connV10.receiveFrame(10000);
|
||||
|
||||
//second receive will get problem if trailing bytes
|
||||
assertEquals("Hello World", frame.getBody());
|
||||
|
||||
System.out.println("received again: " + frame);
|
||||
|
||||
//unsub
|
||||
unsubFrame = connV10.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV10.sendFrame(unsubFrame);
|
||||
testNoGarbageAfterPersistentMessage(connV10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoGarbageAfterPersistentMessageV11() throws Exception {
|
||||
ClientStompFrame subFrame = connV11.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
testNoGarbageAfterPersistentMessage(connV11);
|
||||
}
|
||||
|
||||
connV11.sendFrame(subFrame);
|
||||
ClientStompFrame frame = connV11.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("content-length", "11");
|
||||
frame.addHeader("persistent", "true");
|
||||
public void testNoGarbageAfterPersistentMessage(StompClientConnection conn) throws Exception {
|
||||
subscribe(conn, "a-sub");
|
||||
|
||||
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND);
|
||||
frame.addHeader(Stomp.Headers.Subscribe.DESTINATION, getQueuePrefix() + getQueueName());
|
||||
frame.addHeader(Stomp.Headers.CONTENT_LENGTH, "11");
|
||||
frame.addHeader(Stomp.Headers.Send.PERSISTENT, Boolean.TRUE.toString());
|
||||
frame.setBody("Hello World");
|
||||
|
||||
connV11.sendFrame(frame);
|
||||
conn.sendFrame(frame);
|
||||
|
||||
frame = connV11.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("content-length", "11");
|
||||
frame.addHeader("persistent", "true");
|
||||
frame = conn.createFrame(Stomp.Commands.SEND);
|
||||
frame.addHeader(Stomp.Headers.Subscribe.DESTINATION, getQueuePrefix() + getQueueName());
|
||||
frame.addHeader(Stomp.Headers.CONTENT_LENGTH, "11");
|
||||
frame.addHeader(Stomp.Headers.Send.PERSISTENT, Boolean.TRUE.toString());
|
||||
frame.setBody("Hello World");
|
||||
|
||||
connV11.sendFrame(frame);
|
||||
frame = connV11.receiveFrame(10000);
|
||||
conn.sendFrame(frame);
|
||||
|
||||
System.out.println("received: " + frame);
|
||||
frame = conn.receiveFrame(10000);
|
||||
|
||||
assertEquals("Hello World", frame.getBody());
|
||||
|
||||
//if activemq sends trailing garbage bytes, the second message
|
||||
//will not be normal
|
||||
frame = connV11.receiveFrame(10000);
|
||||
|
||||
System.out.println("received: " + frame);
|
||||
frame = conn.receiveFrame(10000);
|
||||
|
||||
assertEquals("Hello World", frame.getBody());
|
||||
|
||||
//unsub
|
||||
ClientStompFrame unsubFrame = connV11.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV11.sendFrame(unsubFrame);
|
||||
unsubscribe(conn, "a-sub");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoGarbageOnPersistentRedeliveryV10() throws Exception {
|
||||
testNoGarbageOnPersistentRedelivery(connV10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoGarbageOnPersistentRedeliveryV11() throws Exception {
|
||||
ClientStompFrame frame = connV11.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("content-length", "11");
|
||||
frame.addHeader("persistent", "true");
|
||||
testNoGarbageOnPersistentRedelivery(connV11);
|
||||
}
|
||||
|
||||
public void testNoGarbageOnPersistentRedelivery(StompClientConnection conn) throws Exception {
|
||||
ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND);
|
||||
frame.addHeader(Stomp.Headers.Subscribe.DESTINATION, getQueuePrefix() + getQueueName());
|
||||
frame.addHeader(Stomp.Headers.CONTENT_LENGTH, "11");
|
||||
frame.addHeader(Stomp.Headers.Send.PERSISTENT, Boolean.TRUE.toString());
|
||||
frame.setBody("Hello World");
|
||||
|
||||
connV11.sendFrame(frame);
|
||||
conn.sendFrame(frame);
|
||||
|
||||
frame = connV11.createFrame("SEND");
|
||||
frame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
frame.addHeader("content-length", "11");
|
||||
frame.addHeader("persistent", "true");
|
||||
frame = conn.createFrame(Stomp.Commands.SEND);
|
||||
frame.addHeader(Stomp.Headers.Subscribe.DESTINATION, getQueuePrefix() + getQueueName());
|
||||
frame.addHeader(Stomp.Headers.CONTENT_LENGTH, "11");
|
||||
frame.addHeader(Stomp.Headers.Send.PERSISTENT, Boolean.TRUE.toString());
|
||||
frame.setBody("Hello World");
|
||||
|
||||
connV11.sendFrame(frame);
|
||||
conn.sendFrame(frame);
|
||||
|
||||
ClientStompFrame subFrame = connV11.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "client");
|
||||
|
||||
connV11.sendFrame(subFrame);
|
||||
subscribe(conn, "a-sub", Stomp.Headers.Subscribe.AckModeValues.CLIENT);
|
||||
|
||||
// receive but don't ack
|
||||
frame = connV11.receiveFrame(10000);
|
||||
frame = connV11.receiveFrame(10000);
|
||||
frame = conn.receiveFrame(10000);
|
||||
frame = conn.receiveFrame(10000);
|
||||
|
||||
System.out.println("received: " + frame);
|
||||
unsubscribe(conn, "a-sub");
|
||||
|
||||
//unsub
|
||||
ClientStompFrame unsubFrame = connV11.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV11.sendFrame(unsubFrame);
|
||||
subscribe(conn, "a-sub");
|
||||
|
||||
subFrame = connV11.createFrame("SUBSCRIBE");
|
||||
subFrame.addHeader("id", "a-sub");
|
||||
subFrame.addHeader("destination", getQueuePrefix() + getQueueName());
|
||||
subFrame.addHeader("ack", "auto");
|
||||
|
||||
connV11.sendFrame(subFrame);
|
||||
|
||||
frame = connV11.receiveFrame(10000);
|
||||
frame = connV11.receiveFrame(10000);
|
||||
frame = conn.receiveFrame(10000);
|
||||
frame = conn.receiveFrame(10000);
|
||||
|
||||
//second receive will get problem if trailing bytes
|
||||
assertEquals("Hello World", frame.getBody());
|
||||
|
||||
System.out.println("received again: " + frame);
|
||||
|
||||
//unsub
|
||||
unsubFrame = connV11.createFrame("UNSUBSCRIBE");
|
||||
unsubFrame.addHeader("id", "a-sub");
|
||||
connV11.sendFrame(unsubFrame);
|
||||
unsubscribe(conn, "a-sub");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,167 +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.tests.integration.stomp.v11;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.jms.Topic;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.TransportConfiguration;
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.protocol.stomp.StompProtocolManagerFactory;
|
||||
import org.apache.activemq.artemis.core.registry.JndiBindingRegistry;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptorFactory;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServers;
|
||||
import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;
|
||||
import org.apache.activemq.artemis.jms.server.JMSServerManager;
|
||||
import org.apache.activemq.artemis.jms.server.config.JMSConfiguration;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.JMSConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.JMSQueueConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.TopicConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.impl.JMSServerManagerImpl;
|
||||
import org.apache.activemq.artemis.tests.unit.util.InVMNamingContext;
|
||||
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
|
||||
import org.junit.Before;
|
||||
|
||||
public abstract class StompV11TestBase extends ActiveMQTestBase {
|
||||
|
||||
protected String hostname = "127.0.0.1";
|
||||
|
||||
protected int port = 61613;
|
||||
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
||||
private Connection connection;
|
||||
|
||||
protected Session session;
|
||||
|
||||
protected Queue queue;
|
||||
|
||||
protected Topic topic;
|
||||
|
||||
protected JMSServerManager server;
|
||||
|
||||
protected String defUser = "brianm";
|
||||
|
||||
protected String defPass = "wombats";
|
||||
|
||||
protected boolean persistenceEnabled = false;
|
||||
|
||||
// Implementation methods
|
||||
// -------------------------------------------------------------------------
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
server = createServer();
|
||||
server.start();
|
||||
connectionFactory = createConnectionFactory();
|
||||
|
||||
connection = connectionFactory.createConnection();
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
queue = session.createQueue(getQueueName());
|
||||
topic = session.createTopic(getTopicName());
|
||||
connection.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
protected JMSServerManager createServer() throws Exception {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put(TransportConstants.PROTOCOLS_PROP_NAME, StompProtocolManagerFactory.STOMP_PROTOCOL_NAME);
|
||||
params.put(TransportConstants.PORT_PROP_NAME, TransportConstants.DEFAULT_STOMP_PORT);
|
||||
params.put(TransportConstants.STOMP_CONSUMERS_CREDIT, "-1");
|
||||
TransportConfiguration stompTransport = new TransportConfiguration(NettyAcceptorFactory.class.getName(), params);
|
||||
|
||||
Configuration config = createBasicConfig().setPersistenceEnabled(persistenceEnabled).addAcceptorConfiguration(stompTransport).addAcceptorConfiguration(new TransportConfiguration(InVMAcceptorFactory.class.getName())).setConnectionTtlCheckInterval(500);
|
||||
|
||||
ActiveMQServer activeMQServer = addServer(ActiveMQServers.newActiveMQServer(config, defUser, defPass));
|
||||
|
||||
JMSConfiguration jmsConfig = new JMSConfigurationImpl();
|
||||
jmsConfig.getQueueConfigurations().add(new JMSQueueConfigurationImpl().setName(getQueueName()).setBindings(getQueueName()));
|
||||
jmsConfig.getTopicConfigurations().add(new TopicConfigurationImpl().setName(getTopicName()).setBindings(getTopicName()));
|
||||
server = new JMSServerManagerImpl(activeMQServer, jmsConfig);
|
||||
server.setRegistry(new JndiBindingRegistry(new InVMNamingContext()));
|
||||
return server;
|
||||
}
|
||||
|
||||
protected ConnectionFactory createConnectionFactory() {
|
||||
return new ActiveMQJMSConnectionFactory(false, new TransportConfiguration(InVMConnectorFactory.class.getName()));
|
||||
}
|
||||
|
||||
protected String getQueueName() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
protected String getQueuePrefix() {
|
||||
return "";
|
||||
}
|
||||
|
||||
protected String getTopicName() {
|
||||
return "testtopic";
|
||||
}
|
||||
|
||||
protected String getTopicPrefix() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void sendMessage(String msg) throws Exception {
|
||||
sendMessage(msg, queue);
|
||||
}
|
||||
|
||||
public void sendMessage(String msg, Destination destination) throws Exception {
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
TextMessage message = session.createTextMessage(msg);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
public void sendMessage(byte[] data, Destination destination) throws Exception {
|
||||
sendMessage(data, "foo", "xyz", destination);
|
||||
}
|
||||
|
||||
public void sendMessage(String msg, String propertyName, String propertyValue) throws Exception {
|
||||
sendMessage(msg.getBytes(StandardCharsets.UTF_8), propertyName, propertyValue, queue);
|
||||
}
|
||||
|
||||
public void sendMessage(byte[] data,
|
||||
String propertyName,
|
||||
String propertyValue,
|
||||
Destination destination) throws Exception {
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
BytesMessage message = session.createBytesMessage();
|
||||
message.setStringProperty(propertyName, propertyValue);
|
||||
message.writeBytes(data);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -169,11 +169,24 @@ public class JMSClusteredTestBase extends ActiveMQTestBase {
|
|||
final String destinationLabel = "toServer" + destination;
|
||||
final String sourceLabel = "server" + source;
|
||||
|
||||
Configuration configuration = createDefaultInVMConfig(source).setSecurityEnabled(false).setJMXManagementEnabled(true).setPersistenceEnabled(false).addConnectorConfiguration(destinationLabel, new TransportConfiguration(InVMConnectorFactory.class.getName(), generateInVMParams(destination))).addConnectorConfiguration(sourceLabel, new TransportConfiguration(InVMConnectorFactory.class.getName(), generateInVMParams(source))).addClusterConfiguration(new ClusterConnectionConfiguration().setName(destinationLabel).setAddress("jms").setConnectorName(sourceLabel).setRetryInterval(250).setMaxHops(MAX_HOPS).setConfirmationWindowSize(1024).setMessageLoadBalancingType(MessageLoadBalancingType.ON_DEMAND).setStaticConnectors(new ArrayList<String>() {
|
||||
{
|
||||
add(destinationLabel);
|
||||
}
|
||||
}));
|
||||
Configuration configuration = createDefaultInVMConfig(source).setSecurityEnabled(false)
|
||||
.setJMXManagementEnabled(true)
|
||||
.setPersistenceEnabled(false)
|
||||
.addConnectorConfiguration(destinationLabel, new TransportConfiguration(InVMConnectorFactory.class.getName(), generateInVMParams(destination)))
|
||||
.addConnectorConfiguration(sourceLabel, new TransportConfiguration(InVMConnectorFactory.class.getName(), generateInVMParams(source)))
|
||||
.addClusterConfiguration(new ClusterConnectionConfiguration().setName(destinationLabel)
|
||||
// TODO should this be changed?
|
||||
.setAddress("jms")
|
||||
.setConnectorName(sourceLabel)
|
||||
.setRetryInterval(250)
|
||||
.setMaxHops(MAX_HOPS)
|
||||
.setConfirmationWindowSize(1024)
|
||||
.setMessageLoadBalancingType(MessageLoadBalancingType.ON_DEMAND)
|
||||
.setStaticConnectors(new ArrayList<String>() {
|
||||
{
|
||||
add(destinationLabel);
|
||||
}
|
||||
}));
|
||||
|
||||
configuration.getAddressesSettings().put("#", new AddressSettings().setRedistributionDelay(0));
|
||||
|
||||
|
|
|
@ -340,6 +340,7 @@ public class MessageProducerTest extends JMSTestCase {
|
|||
@Test
|
||||
public void testCreateProducerOnInexistentDestination() throws Exception {
|
||||
getJmsServer().getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateJmsQueues(false));
|
||||
getJmsServer().getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateJmsTopics(false));
|
||||
Connection pconn = createConnection();
|
||||
try {
|
||||
Session ps = pconn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
|
|
@ -170,6 +170,7 @@ public class SessionTest extends ActiveMQServerTestCase {
|
|||
@Test
|
||||
public void testCreateNonExistentTopic() throws Exception {
|
||||
getJmsServer().getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateJmsQueues(false));
|
||||
getJmsServer().getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateJmsTopics(false));
|
||||
Connection conn = getConnectionFactory().createConnection();
|
||||
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
try {
|
||||
|
@ -198,6 +199,7 @@ public class SessionTest extends ActiveMQServerTestCase {
|
|||
@Test
|
||||
public void testCreateTopicWhileQueueWithSameNameExists() throws Exception {
|
||||
getJmsServer().getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateJmsQueues(false));
|
||||
getJmsServer().getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateJmsTopics(false));
|
||||
Connection conn = getConnectionFactory().createConnection();
|
||||
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
try {
|
||||
|
|
|
@ -1125,7 +1125,7 @@ public class MessageHeaderTest extends MessageHeaderTestBase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void createAddress(SimpleString address, boolean multicast) throws ActiveMQException {
|
||||
public void createAddress(SimpleString address, boolean multicast, final boolean autoCreated) throws ActiveMQException {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.apache.activemq.artemis.core.postoffice.RoutingStatus;
|
|||
import org.apache.activemq.artemis.core.postoffice.impl.DuplicateIDCacheImpl;
|
||||
import org.apache.activemq.artemis.core.server.MessageReference;
|
||||
import org.apache.activemq.artemis.core.server.Queue;
|
||||
import org.apache.activemq.artemis.core.server.QueueCreator;
|
||||
import org.apache.activemq.artemis.core.server.RoutingContext;
|
||||
import org.apache.activemq.artemis.core.server.ServerMessage;
|
||||
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
|
||||
|
@ -162,7 +161,6 @@ public class FakePostOffice implements PostOffice {
|
|||
|
||||
@Override
|
||||
public RoutingStatus route(ServerMessage message,
|
||||
QueueCreator creator,
|
||||
RoutingContext context,
|
||||
boolean direct) throws Exception {
|
||||
return RoutingStatus.OK;
|
||||
|
@ -171,7 +169,6 @@ public class FakePostOffice implements PostOffice {
|
|||
|
||||
@Override
|
||||
public RoutingStatus route(ServerMessage message,
|
||||
QueueCreator creator,
|
||||
Transaction tx,
|
||||
boolean direct) throws Exception {
|
||||
return RoutingStatus.OK;
|
||||
|
@ -179,7 +176,6 @@ public class FakePostOffice implements PostOffice {
|
|||
|
||||
@Override
|
||||
public RoutingStatus route(ServerMessage message,
|
||||
QueueCreator creator,
|
||||
RoutingContext context,
|
||||
boolean direct,
|
||||
boolean rejectDuplicates) throws Exception {
|
||||
|
@ -189,7 +185,6 @@ public class FakePostOffice implements PostOffice {
|
|||
|
||||
@Override
|
||||
public RoutingStatus route(ServerMessage message,
|
||||
QueueCreator creator,
|
||||
Transaction tx,
|
||||
boolean direct,
|
||||
boolean rejectDuplicates) throws Exception {
|
||||
|
@ -201,7 +196,7 @@ public class FakePostOffice implements PostOffice {
|
|||
}
|
||||
|
||||
@Override
|
||||
public RoutingStatus route(ServerMessage message, QueueCreator queueCreator, boolean direct) throws Exception {
|
||||
public RoutingStatus route(ServerMessage message, boolean direct) throws Exception {
|
||||
return RoutingStatus.OK;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue