/*
* 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.rest.test;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.activemq.artemis.rest.queue.QueueDeployment;
import org.apache.activemq.artemis.rest.queue.push.ActiveMQPushStrategy;
import org.apache.activemq.artemis.rest.queue.push.xml.PushRegistration;
import org.apache.activemq.artemis.rest.queue.push.xml.XmlLink;
import org.apache.activemq.artemis.rest.util.Constants;
import org.jboss.resteasy.client.ClientRequest;
import org.jboss.resteasy.client.ClientResponse;
import org.jboss.resteasy.spi.Link;
import org.junit.Assert;
import org.junit.Test;
import static org.jboss.resteasy.test.TestPortProvider.generateURL;
public class PushQueueConsumerTest extends MessageTestBase {
enum PushRegistrationType {
CLASS, BRIDGE, URI, TEMPLATE
}
@Test
public void testBridge() throws Exception {
Link destinationForConsumption = null;
ClientResponse consumerResponse = null;
Link pushSubscription = null;
String messageContent = "1";
try {
// The name of the queue used for the test should match the name of the test
String queue = "testBridge";
String queueToPushTo = "pushedFrom-" + queue;
System.out.println("\n" + queue);
deployQueue(queue);
deployQueue(queueToPushTo);
ClientResponse queueResponse = Util.head(new ClientRequest(generateURL(Util.getUrlPath(queue))));
Link destination = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), queueResponse, "create");
Link pushSubscriptions = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), queueResponse, "push-consumers");
ClientResponse queueToPushToResponse = Util.head(new ClientRequest(generateURL(Util.getUrlPath(queueToPushTo))));
ClientResponse autoAckResponse = setAutoAck(queueToPushToResponse, true);
destinationForConsumption = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), autoAckResponse, "consume-next");
pushSubscription = createPushRegistration(queueToPushTo, pushSubscriptions, PushRegistrationType.BRIDGE);
sendMessage(destination, messageContent);
consumerResponse = consume(destinationForConsumption, messageContent);
} finally {
cleanupConsumer(consumerResponse);
cleanupSubscription(pushSubscription);
}
}
private void cleanupSubscription(Link pushSubscription) throws Exception {
if (pushSubscription != null) {
ClientResponse<?> response = pushSubscription.request().delete();
response.releaseConnection();
Assert.assertEquals(204, response.getStatus());
}
}
@Test
public void testClass() throws Exception {
Link destinationForConsumption = null;
ClientResponse consumerResponse = null;
Link pushSubscription = null;
String messageContent = "1";
try {
// The name of the queue used for the test should match the name of the test
String queue = "testClass";
String queueToPushTo = "pushedFrom-" + queue;
System.out.println("\n" + queue);
deployQueue(queue);
deployQueue(queueToPushTo);
ClientResponse queueResponse = Util.head(new ClientRequest(generateURL(Util.getUrlPath(queue))));
Link destinationForSend = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), queueResponse, "create");
Link pushSubscriptions = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), queueResponse, "push-consumers");
ClientResponse queueToPushToResponse = Util.head(new ClientRequest(generateURL(Util.getUrlPath(queueToPushTo))));
ClientResponse autoAckResponse = setAutoAck(queueToPushToResponse, true);
destinationForConsumption = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), autoAckResponse, "consume-next");
pushSubscription = createPushRegistration(queueToPushTo, pushSubscriptions, PushRegistrationType.CLASS);
sendMessage(destinationForSend, messageContent);
consumerResponse = consume(destinationForConsumption, messageContent);
} finally {
cleanupConsumer(consumerResponse);
cleanupSubscription(pushSubscription);
}
}
@Test
public void testTemplate() throws Exception {
Link destinationForConsumption = null;
ClientResponse consumerResponse = null;
Link pushSubscription = null;
String messageContent = "1";
try {
// The name of the queue used for the test should match the name of the test
String queue = "testTemplate";
String queueToPushTo = "pushedFrom-" + queue;
System.out.println("\n" + queue);
deployQueue(queue);
deployQueue(queueToPushTo);
ClientResponse queueResponse = Util.head(new ClientRequest(generateURL(Util.getUrlPath(queue))));
Link destinationForSend = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), queueResponse, "create");
Link pushSubscriptions = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), queueResponse, "push-consumers");
ClientResponse queueToPushToResponse = Util.head(new ClientRequest(generateURL(Util.getUrlPath(queueToPushTo))));
Link consumers = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), queueToPushToResponse, "pull-consumers");
Link createWithId = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), queueToPushToResponse, "create-with-id");
ClientResponse autoAckResponse = Util.setAutoAck(consumers, true);
destinationForConsumption = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), autoAckResponse, "consume-next");
pushSubscription = createPushRegistration(createWithId.getHref(), pushSubscriptions, PushRegistrationType.TEMPLATE);
sendMessage(destinationForSend, messageContent);
consumerResponse = consume(destinationForConsumption, messageContent);
} finally {
cleanupConsumer(consumerResponse);
cleanupSubscription(pushSubscription);
}
}
@Path("/my")
public static class MyResource {
public static String got_it;
@PUT
public void put(String str) {
got_it = str;
}
}
@Path("/myConcurrent")
public static class MyConcurrentResource {
public static AtomicInteger concurrentInvocations = new AtomicInteger();
public static AtomicInteger maxConcurrentInvocations = new AtomicInteger();
@PUT
public void put(String str) {
concurrentInvocations.getAndIncrement();
if (concurrentInvocations.get() > maxConcurrentInvocations.get()) {
maxConcurrentInvocations.set(concurrentInvocations.get());
}
try {
// sleep here so the concurrent invocations can stack up
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
concurrentInvocations.getAndDecrement();
}
}
@Test
public void testUri() throws Exception {
Link pushSubscription = null;
String messageContent = "1";
try {
// The name of the queue used for the test should match the name of the test
String queue = "testUri";
String queueToPushTo = "pushedFrom-" + queue;
System.out.println("\n" + queue);
deployQueue(queue);
deployQueue(queueToPushTo);
server.getJaxrsServer().getDeployment().getRegistry().addPerRequestResource(MyResource.class);
ClientResponse queueResponse = Util.head(new ClientRequest(generateURL(Util.getUrlPath(queue))));
Link destinationForSend = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), queueResponse, "create");
Link pushSubscriptions = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), queueResponse, "push-consumers");
pushSubscription = createPushRegistration(generateURL("/my"), pushSubscriptions, PushRegistrationType.URI);
sendMessage(destinationForSend, messageContent);
Thread.sleep(100);
Assert.assertEquals(messageContent, MyResource.got_it);
} finally {
cleanupSubscription(pushSubscription);
}
}
@Test
public void testUriWithMultipleSessions() throws Exception {
Link pushSubscription = null;
String messageContent = "1";
final int CONCURRENT = 10;
try {
// The name of the queue used for the test should match the name of the test
String queue = "testUriWithMultipleSessions";
String queueToPushTo = "pushedFrom-" + queue;
System.out.println("\n" + queue);
deployQueue(queue);
deployQueue(queueToPushTo);
server.getJaxrsServer().getDeployment().getRegistry().addPerRequestResource(MyConcurrentResource.class);
ClientResponse queueResponse = Util.head(new ClientRequest(generateURL(Util.getUrlPath(queue))));
Link destinationForSend = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), queueResponse, "create");
Link pushSubscriptions = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), queueResponse, "push-consumers");
pushSubscription = createPushRegistration(generateURL("/myConcurrent"), pushSubscriptions, PushRegistrationType.URI, CONCURRENT);
for (int i = 0; i < CONCURRENT; i++) {
sendMessage(destinationForSend, messageContent);
}
// wait until all the invocations have completed
while (MyConcurrentResource.concurrentInvocations.get() > 0) {
Thread.sleep(100);
}
Assert.assertEquals(CONCURRENT, MyConcurrentResource.maxConcurrentInvocations.get());
} finally {
cleanupSubscription(pushSubscription);
}
}
private void deployQueue(String queueName) throws Exception {
QueueDeployment deployment = new QueueDeployment();
deployment.setDuplicatesAllowed(true);
deployment.setDurableSend(false);
deployment.setName(queueName);
manager.getQueueManager().deploy(deployment);
}
private ClientResponse consume(Link destination, String expectedContent) throws Exception {
ClientResponse response;
response = destination.request().header(Constants.WAIT_HEADER, "1").post(String.class);
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals(expectedContent, response.getEntity(String.class));
response.releaseConnection();
return response;
}
private void sendMessage(Link sender, String content) throws Exception {
ClientResponse sendMessageResponse = sender.request().body("text/plain", content).post();
sendMessageResponse.releaseConnection();
Assert.assertEquals(201, sendMessageResponse.getStatus());
}
private ClientResponse setAutoAck(ClientResponse response, boolean ack) throws Exception {
Link pullConsumers = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), response, "pull-consumers");
ClientResponse autoAckResponse = pullConsumers.request().formParameter("autoAck", Boolean.toString(ack)).post();
autoAckResponse.releaseConnection();
Assert.assertEquals(201, autoAckResponse.getStatus());
return autoAckResponse;
}
private void cleanupConsumer(ClientResponse consumerResponse) throws Exception {
if (consumerResponse != null) {
Link consumer = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), consumerResponse, "consumer");
ClientResponse<?> response = consumer.request().delete();
response.releaseConnection();
Assert.assertEquals(204, response.getStatus());
}
}
private Link createPushRegistration(String queueToPushTo,
Link pushSubscriptions,
PushRegistrationType pushRegistrationType) throws Exception {
return createPushRegistration(queueToPushTo, pushSubscriptions, pushRegistrationType, 1);
}
private Link createPushRegistration(String queueToPushTo,
Link pushSubscriptions,
PushRegistrationType pushRegistrationType,
int sessionCount) throws Exception {
PushRegistration reg = new PushRegistration();
reg.setDurable(false);
XmlLink target = new XmlLink();
if (pushRegistrationType == PushRegistrationType.CLASS) {
target.setHref(generateURL(Util.getUrlPath(queueToPushTo)));
target.setClassName(ActiveMQPushStrategy.class.getName());
} else if (pushRegistrationType == PushRegistrationType.BRIDGE) {
target.setHref(generateURL(Util.getUrlPath(queueToPushTo)));
target.setRelationship("destination");
} else if (pushRegistrationType == PushRegistrationType.TEMPLATE) {
target.setHref(queueToPushTo);
target.setRelationship("template");
} else if (pushRegistrationType == PushRegistrationType.URI) {
target.setMethod("put");
target.setHref(queueToPushTo);
}
reg.setTarget(target);
reg.setSessionCount(sessionCount);
ClientResponse pushRegistrationResponse = pushSubscriptions.request().body("application/xml", reg).post();
pushRegistrationResponse.releaseConnection();
Assert.assertEquals(201, pushRegistrationResponse.getStatus());
Link pushSubscription = pushRegistrationResponse.getLocationLink();
return pushSubscription;
}
}