ARTEMIS-3758: clean up lots of tests that never run, remove related files + dependencies and some unnecessary deps
This commit is contained in:
parent
94aa67bd81
commit
6da678177a
|
@ -29,16 +29,6 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<activemq.basedir>${project.basedir}/../..</activemq.basedir>
|
<activemq.basedir>${project.basedir}/../..</activemq.basedir>
|
||||||
<jmdns-version>3.4.1</jmdns-version>
|
|
||||||
<ftpserver-version>1.0.6</ftpserver-version>
|
|
||||||
<jmock-version>2.5.1</jmock-version>
|
|
||||||
<spring-version>5.3.18</spring-version>
|
|
||||||
<org-apache-derby-version>10.11.1.1</org-apache-derby-version>
|
|
||||||
<commons-net-version>3.3</commons-net-version>
|
|
||||||
<xbean-version>3.18</xbean-version>
|
|
||||||
<hamcrest-version>1.3</hamcrest-version>
|
|
||||||
<jasypt-version>1.9.3</jasypt-version>
|
|
||||||
<activeio-core-version>3.1.4</activeio-core-version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -93,18 +83,6 @@
|
||||||
<version>${activemq5-version}</version>
|
<version>${activemq5-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.activemq</groupId>
|
|
||||||
<artifactId>activemq-leveldb-store</artifactId>
|
|
||||||
<version>${activemq5-version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>commons-beanutils</groupId>
|
|
||||||
<artifactId>commons-beanutils-core</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.activemq</groupId>
|
<groupId>org.apache.activemq</groupId>
|
||||||
<artifactId>activemq-pool</artifactId>
|
<artifactId>activemq-pool</artifactId>
|
||||||
|
@ -117,36 +95,12 @@
|
||||||
<version>${activemq5-version}</version>
|
<version>${activemq5-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.activemq</groupId>
|
|
||||||
<artifactId>activemq-partition</artifactId>
|
|
||||||
<version>${activemq5-version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>log4j</groupId>
|
|
||||||
<artifactId>log4j</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.activemq</groupId>
|
<groupId>org.apache.activemq</groupId>
|
||||||
<artifactId>activemq-stomp</artifactId>
|
<artifactId>activemq-stomp</artifactId>
|
||||||
<version>${activemq5-version}</version>
|
<version>${activemq5-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.activemq</groupId>
|
|
||||||
<artifactId>activemq-console</artifactId>
|
|
||||||
<version>${activemq5-version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.activemq</groupId>
|
|
||||||
<artifactId>activeio-core</artifactId>
|
|
||||||
<version>${activeio-core-version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
@ -159,137 +113,23 @@
|
||||||
<version>4.3.1</version>
|
<version>4.3.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.jmdns</groupId>
|
|
||||||
<artifactId>jmdns</artifactId>
|
|
||||||
<version>${jmdns-version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.ftpserver</groupId>
|
|
||||||
<artifactId>ftpserver-core</artifactId>
|
|
||||||
<version>${ftpserver-version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jmock</groupId>
|
|
||||||
<artifactId>jmock-junit4</artifactId>
|
|
||||||
<version>${jmock-version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jmock</groupId>
|
|
||||||
<artifactId>jmock-legacy</artifactId>
|
|
||||||
<version>${jmock-version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-jms</artifactId>
|
|
||||||
<version>${spring-version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.derby</groupId>
|
<groupId>org.apache.derby</groupId>
|
||||||
<artifactId>derby</artifactId>
|
<artifactId>derby</artifactId>
|
||||||
<version>${org-apache-derby-version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-io</groupId>
|
|
||||||
<artifactId>commons-io</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-net</groupId>
|
|
||||||
<artifactId>commons-net</artifactId>
|
|
||||||
<version>${commons-net-version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.xbean</groupId>
|
|
||||||
<artifactId>xbean-spring</artifactId>
|
|
||||||
<version>${xbean-version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hamcrest</groupId>
|
|
||||||
<artifactId>hamcrest-all</artifactId>
|
|
||||||
<version>${hamcrest-version}</version>
|
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-context</artifactId>
|
<artifactId>spring-context</artifactId>
|
||||||
<version>${spring-version}</version>
|
<version>${spring.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-test</artifactId>
|
<artifactId>spring-test</artifactId>
|
||||||
<version>${spring-version}</version>
|
<version>${spring.version}</version>
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jasypt</groupId>
|
|
||||||
<artifactId>jasypt</artifactId>
|
|
||||||
<version>${jasypt-version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jasypt</groupId>
|
|
||||||
<artifactId>jasypt-spring31</artifactId>
|
|
||||||
<version>${jasypt-version}</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.directory.server</groupId>
|
|
||||||
<artifactId>apacheds-core-integ</artifactId>
|
|
||||||
<version>${directory-version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.directory.server</groupId>
|
|
||||||
<artifactId>apacheds-server-integ</artifactId>
|
|
||||||
<version>${directory-version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>log4j</groupId>
|
|
||||||
<artifactId>log4j</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.fusesource.joram-jms-tests</groupId>
|
|
||||||
<artifactId>joram-jms-tests</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.easymock</groupId>
|
|
||||||
<artifactId>easymock</artifactId>
|
|
||||||
<version>3.2</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.fusesource.mqtt-client</groupId>
|
|
||||||
<artifactId>mqtt-client</artifactId>
|
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<!-- START SNIPPET: xbean -->
|
|
||||||
<beans
|
|
||||||
xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:amq="http://activemq.apache.org/schema/core"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
|
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
|
||||||
|
|
||||||
<bean id="config" class="java.lang.String">
|
|
||||||
<constructor-arg><value>
|
|
||||||
<![CDATA[
|
|
||||||
{
|
|
||||||
"by_client_id":{
|
|
||||||
"client1":{"ids":["broker1"]},
|
|
||||||
"client2":{"ids":["broker1","broker2"]}
|
|
||||||
},
|
|
||||||
"brokers":{
|
|
||||||
"broker1":"tcp://localhost:61616",
|
|
||||||
"broker2":"tcp://localhost:61616"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</value></constructor-arg>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<broker useJmx="false" xmlns="http://activemq.apache.org/schema/core" persistent="false">
|
|
||||||
|
|
||||||
<plugins>
|
|
||||||
<partitionBrokerPlugin minTransferCount="5" configAsJson="#config"/>
|
|
||||||
</plugins>
|
|
||||||
|
|
||||||
<transportConnectors>
|
|
||||||
<transportConnector uri="tcp://localhost:61616"/>
|
|
||||||
</transportConnectors>
|
|
||||||
|
|
||||||
</broker>
|
|
||||||
|
|
||||||
</beans>
|
|
||||||
<!-- END SNIPPET: xbean -->
|
|
|
@ -1,37 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<!-- START SNIPPET: xbean -->
|
|
||||||
<beans
|
|
||||||
xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:amq="http://activemq.apache.org/schema/core"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
|
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
|
||||||
|
|
||||||
<broker useJmx="false" xmlns="http://activemq.apache.org/schema/core" persistent="false">
|
|
||||||
|
|
||||||
<transportConnectors>
|
|
||||||
<transportConnector uri="nio://localhost:61616?wireFormat.maxFrameSize=1048576" />
|
|
||||||
</transportConnectors>
|
|
||||||
|
|
||||||
</broker>
|
|
||||||
|
|
||||||
</beans>
|
|
||||||
<!-- END SNIPPET: xbean -->
|
|
|
@ -32,7 +32,6 @@ import org.apache.activemq.command.ActiveMQDestination;
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
import org.apache.activemq.command.ActiveMQQueue;
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
import org.apache.activemq.command.ActiveMQTopic;
|
||||||
import org.junit.rules.TemporaryFolder;
|
import org.junit.rules.TemporaryFolder;
|
||||||
import org.springframework.jms.core.JmsTemplate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A useful base class which creates and closes an embedded broker
|
* A useful base class which creates and closes an embedded broker
|
||||||
|
@ -45,7 +44,6 @@ public abstract class EmbeddedBrokerTestSupport extends CombinationTestSupport {
|
||||||
protected ConnectionFactory connectionFactory;
|
protected ConnectionFactory connectionFactory;
|
||||||
protected boolean useTopic;
|
protected boolean useTopic;
|
||||||
protected ActiveMQDestination destination;
|
protected ActiveMQDestination destination;
|
||||||
protected JmsTemplate template;
|
|
||||||
protected boolean disableWrapper = false;
|
protected boolean disableWrapper = false;
|
||||||
|
|
||||||
public TemporaryFolder temporaryFolder;
|
public TemporaryFolder temporaryFolder;
|
||||||
|
@ -68,11 +66,6 @@ public abstract class EmbeddedBrokerTestSupport extends CombinationTestSupport {
|
||||||
connectionFactory = createConnectionFactory();
|
connectionFactory = createConnectionFactory();
|
||||||
|
|
||||||
destination = createDestination();
|
destination = createDestination();
|
||||||
|
|
||||||
template = createJmsTemplate();
|
|
||||||
template.setDefaultDestination(destination);
|
|
||||||
template.setPubSubDomain(useTopic);
|
|
||||||
template.afterPropertiesSet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -115,15 +108,6 @@ public abstract class EmbeddedBrokerTestSupport extends CombinationTestSupport {
|
||||||
return "tcp://" + localhostAddress + ":" + (61616 + serverID);
|
return "tcp://" + localhostAddress + ":" + (61616 + serverID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to create a new {@link JmsTemplate}
|
|
||||||
*
|
|
||||||
* @return a newly created JmsTemplate
|
|
||||||
*/
|
|
||||||
protected JmsTemplate createJmsTemplate() {
|
|
||||||
return new JmsTemplate(connectionFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method to create a new {@link Destination}
|
* Factory method to create a new {@link Destination}
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,668 +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;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
import javax.jms.DeliveryMode;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Queue;
|
|
||||||
import javax.jms.QueueBrowser;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TextMessage;
|
|
||||||
import javax.jms.Topic;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import org.apache.activemq.advisory.ConsumerEvent;
|
|
||||||
import org.apache.activemq.advisory.ConsumerEventSource;
|
|
||||||
import org.apache.activemq.advisory.ConsumerListener;
|
|
||||||
import org.apache.activemq.broker.BrokerFactory;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.TransportConnector;
|
|
||||||
import org.apache.activemq.broker.region.RegionBroker;
|
|
||||||
import org.apache.activemq.broker.region.TopicRegion;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
|
||||||
import org.apache.activemq.command.BrokerInfo;
|
|
||||||
import org.apache.activemq.network.DiscoveryNetworkConnector;
|
|
||||||
import org.apache.activemq.network.NetworkBridge;
|
|
||||||
import org.apache.activemq.network.NetworkConnector;
|
|
||||||
import org.apache.activemq.util.IdGenerator;
|
|
||||||
import org.apache.activemq.util.MessageIdList;
|
|
||||||
import org.apache.activemq.util.Wait;
|
|
||||||
import org.apache.activemq.xbean.BrokerFactoryBean;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test case support that allows the easy management and connection of several
|
|
||||||
* brokers.
|
|
||||||
*/
|
|
||||||
public class JmsMultipleBrokersTestSupport extends CombinationTestSupport {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(JmsMultipleBrokersTestSupport.class);
|
|
||||||
public static final String AUTO_ASSIGN_TRANSPORT = "tcp://localhost:0";
|
|
||||||
public static int maxSetupTime = 5000;
|
|
||||||
|
|
||||||
protected Map<String, BrokerItem> brokers;
|
|
||||||
protected Map<String, Destination> destinations;
|
|
||||||
|
|
||||||
protected int messageSize = 1;
|
|
||||||
|
|
||||||
protected boolean persistentDelivery = true;
|
|
||||||
protected boolean verbose;
|
|
||||||
|
|
||||||
protected NetworkConnector bridgeBrokers(String localBrokerName, String remoteBrokerName) throws Exception {
|
|
||||||
return bridgeBrokers(localBrokerName, remoteBrokerName, false, 1, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected NetworkConnector bridgeBrokers(String localBrokerName,
|
|
||||||
String remoteBrokerName,
|
|
||||||
boolean dynamicOnly) throws Exception {
|
|
||||||
BrokerService localBroker = brokers.get(localBrokerName).broker;
|
|
||||||
BrokerService remoteBroker = brokers.get(remoteBrokerName).broker;
|
|
||||||
|
|
||||||
return bridgeBrokers(localBroker, remoteBroker, dynamicOnly, 1, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected NetworkConnector bridgeBrokers(String localBrokerName,
|
|
||||||
String remoteBrokerName,
|
|
||||||
boolean dynamicOnly,
|
|
||||||
int networkTTL,
|
|
||||||
boolean conduit) throws Exception {
|
|
||||||
BrokerService localBroker = brokers.get(localBrokerName).broker;
|
|
||||||
BrokerService remoteBroker = brokers.get(remoteBrokerName).broker;
|
|
||||||
|
|
||||||
return bridgeBrokers(localBroker, remoteBroker, dynamicOnly, networkTTL, conduit, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overwrite this method to specify how you want to bridge the two brokers
|
|
||||||
// By default, bridge them using add network connector of the local broker
|
|
||||||
// and the first connector of the remote broker
|
|
||||||
protected NetworkConnector bridgeBrokers(BrokerService localBroker,
|
|
||||||
BrokerService remoteBroker,
|
|
||||||
boolean dynamicOnly,
|
|
||||||
int networkTTL,
|
|
||||||
boolean conduit,
|
|
||||||
boolean failover) throws Exception {
|
|
||||||
List<TransportConnector> transportConnectors = remoteBroker.getTransportConnectors();
|
|
||||||
URI remoteURI;
|
|
||||||
if (!transportConnectors.isEmpty()) {
|
|
||||||
remoteURI = transportConnectors.get(0).getConnectUri();
|
|
||||||
String uri = "static:(" + remoteURI + ")";
|
|
||||||
if (failover) {
|
|
||||||
uri = "static:(failover:(" + remoteURI + "))";
|
|
||||||
}
|
|
||||||
NetworkConnector connector = new DiscoveryNetworkConnector(new URI(uri));
|
|
||||||
connector.setName("to-" + remoteBroker.getBrokerName());
|
|
||||||
connector.setDynamicOnly(dynamicOnly);
|
|
||||||
connector.setNetworkTTL(networkTTL);
|
|
||||||
connector.setConduitSubscriptions(conduit);
|
|
||||||
localBroker.addNetworkConnector(connector);
|
|
||||||
maxSetupTime = 2000;
|
|
||||||
return connector;
|
|
||||||
} else {
|
|
||||||
throw new Exception("Remote broker has no registered connectors.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// This will interconnect all brokers using multicast
|
|
||||||
protected void bridgeAllBrokers() throws Exception {
|
|
||||||
bridgeAllBrokers("default", 1, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void bridgeAllBrokers(String groupName, int ttl, boolean suppressduplicateQueueSubs) throws Exception {
|
|
||||||
bridgeAllBrokers(groupName, ttl, suppressduplicateQueueSubs, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void bridgeAllBrokers(String groupName,
|
|
||||||
int ttl,
|
|
||||||
boolean suppressduplicateQueueSubs,
|
|
||||||
boolean decreasePriority) throws Exception {
|
|
||||||
Collection<BrokerItem> brokerList = brokers.values();
|
|
||||||
for (Iterator<BrokerItem> i = brokerList.iterator(); i.hasNext(); ) {
|
|
||||||
BrokerService broker = i.next().broker;
|
|
||||||
List<TransportConnector> transportConnectors = broker.getTransportConnectors();
|
|
||||||
|
|
||||||
if (transportConnectors.isEmpty()) {
|
|
||||||
broker.addConnector(new URI(AUTO_ASSIGN_TRANSPORT));
|
|
||||||
transportConnectors = broker.getTransportConnectors();
|
|
||||||
}
|
|
||||||
|
|
||||||
TransportConnector transport = transportConnectors.get(0);
|
|
||||||
transport.setDiscoveryUri(new URI("multicast://default?group=" + groupName));
|
|
||||||
NetworkConnector nc = broker.addNetworkConnector("multicast://default?group=" + groupName);
|
|
||||||
nc.setNetworkTTL(ttl);
|
|
||||||
nc.setSuppressDuplicateQueueSubscriptions(suppressduplicateQueueSubs);
|
|
||||||
nc.setDecreaseNetworkConsumerPriority(decreasePriority);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multicasting may take longer to setup
|
|
||||||
maxSetupTime = 8000;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void waitForBridgeFormation(final int min) throws Exception {
|
|
||||||
for (BrokerItem brokerItem : brokers.values()) {
|
|
||||||
final BrokerService broker = brokerItem.broker;
|
|
||||||
waitForBridgeFormation(broker, min, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean waitForBridgeFormation(final BrokerService broker,
|
|
||||||
final int min,
|
|
||||||
final int bridgeIndex) throws Exception {
|
|
||||||
return waitForBridgeFormation(broker, min, bridgeIndex, Wait.MAX_WAIT_MILLIS * 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean waitForBridgeFormation(final BrokerService broker,
|
|
||||||
final int min,
|
|
||||||
final int bridgeIndex,
|
|
||||||
long wait) throws Exception {
|
|
||||||
|
|
||||||
boolean result = false;
|
|
||||||
if (!broker.getNetworkConnectors().isEmpty()) {
|
|
||||||
result = Wait.waitFor(new Wait.Condition() {
|
|
||||||
@Override
|
|
||||||
public boolean isSatisified() throws Exception {
|
|
||||||
int activeCount = 0;
|
|
||||||
for (NetworkBridge bridge : broker.getNetworkConnectors().get(bridgeIndex).activeBridges()) {
|
|
||||||
if (bridge.getRemoteBrokerName() != null) {
|
|
||||||
LOG.info("found bridge[" + bridge + "] to " + bridge.getRemoteBrokerName() + " on broker :" + broker.getBrokerName());
|
|
||||||
activeCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return activeCount >= min;
|
|
||||||
}
|
|
||||||
}, wait);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void waitForMinTopicRegionConsumerCount(final String name, final int count) throws Exception {
|
|
||||||
final BrokerService broker = brokers.get(name).broker;
|
|
||||||
final TopicRegion topicRegion = (TopicRegion) ((RegionBroker) broker.getRegionBroker()).getTopicRegion();
|
|
||||||
assertTrue("found expected consumers in topic region of" + name, Wait.waitFor(new Wait.Condition() {
|
|
||||||
@Override
|
|
||||||
public boolean isSatisified() throws Exception {
|
|
||||||
LOG.info("topic consumers: " + name + ", " + topicRegion.getSubscriptions().toString());
|
|
||||||
return topicRegion.getSubscriptions().size() >= count;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timed wait for {@link #hasBridge(String, String)}.
|
|
||||||
*
|
|
||||||
* @param localBrokerName - the name of the broker on the "local" side of the bridge
|
|
||||||
* @param remoteBrokerName - the name of the broker on the "remote" side of the bridge
|
|
||||||
* @param time - the maximum time to wait for the bridge to be established
|
|
||||||
* @param units - the units for <param>time</param>
|
|
||||||
* @throws InterruptedException - if the calling thread is interrupted
|
|
||||||
* @throws TimeoutException - if the bridge is not established within the time limit
|
|
||||||
* @throws Exception - some other unknown error occurs
|
|
||||||
* @see #hasBridge(String, String)
|
|
||||||
*/
|
|
||||||
protected void waitForBridge(final String localBrokerName,
|
|
||||||
final String remoteBrokerName,
|
|
||||||
long time,
|
|
||||||
TimeUnit units) throws InterruptedException, TimeoutException, Exception {
|
|
||||||
if (!Wait.waitFor(new Wait.Condition() {
|
|
||||||
@Override
|
|
||||||
public boolean isSatisified() {
|
|
||||||
return hasBridge(localBrokerName, remoteBrokerName);
|
|
||||||
}
|
|
||||||
}, units.toMillis(time))) {
|
|
||||||
throw new TimeoutException("Bridge not established from broker " + localBrokerName + " to " + remoteBrokerName + " within " + units.toMillis(time) + " milliseconds.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether a bridge has been established between the specified
|
|
||||||
* brokers.Establishment means that connections have been created and broker
|
|
||||||
* info has been exchanged. Due to the asynchronous nature of the
|
|
||||||
* connections, there is still a possibility that the bridge may fail
|
|
||||||
* shortly after establishment.
|
|
||||||
*
|
|
||||||
* @param localBrokerName - the name of the broker on the "local" side of the bridge
|
|
||||||
* @param remoteBrokerName - the name of the broker on the "remote" side of the bridge
|
|
||||||
*/
|
|
||||||
protected boolean hasBridge(String localBrokerName, String remoteBrokerName) {
|
|
||||||
final BrokerItem fromBroker = brokers.get(localBrokerName);
|
|
||||||
if (fromBroker == null) {
|
|
||||||
throw new IllegalArgumentException("Unknown broker: " + localBrokerName);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BrokerInfo peerInfo : fromBroker.broker.getRegionBroker().getPeerBrokerInfos()) {
|
|
||||||
if (peerInfo.getBrokerName().equals(remoteBrokerName)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void waitForBridgeFormation() throws Exception {
|
|
||||||
waitForBridgeFormation(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void startAllBrokers() throws Exception {
|
|
||||||
Collection<BrokerItem> brokerList = brokers.values();
|
|
||||||
for (Iterator<BrokerItem> i = brokerList.iterator(); i.hasNext(); ) {
|
|
||||||
BrokerService broker = i.next().broker;
|
|
||||||
broker.start();
|
|
||||||
broker.waitUntilStarted();
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread.sleep(maxSetupTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BrokerService createBroker(String brokerName) throws Exception {
|
|
||||||
BrokerService broker = new BrokerService();
|
|
||||||
broker.setBrokerName(brokerName);
|
|
||||||
brokers.put(brokerName, new BrokerItem(broker));
|
|
||||||
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BrokerService createBroker(URI brokerUri) throws Exception {
|
|
||||||
BrokerService broker = BrokerFactory.createBroker(brokerUri);
|
|
||||||
configureBroker(broker);
|
|
||||||
brokers.put(broker.getBrokerName(), new BrokerItem(broker));
|
|
||||||
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void configureBroker(BrokerService broker) {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BrokerService createBroker(Resource configFile) throws Exception {
|
|
||||||
BrokerFactoryBean brokerFactory = new BrokerFactoryBean(configFile);
|
|
||||||
brokerFactory.afterPropertiesSet();
|
|
||||||
|
|
||||||
BrokerService broker = brokerFactory.getBroker();
|
|
||||||
brokers.put(broker.getBrokerName(), new BrokerItem(broker));
|
|
||||||
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ConnectionFactory getConnectionFactory(String brokerName) throws Exception {
|
|
||||||
BrokerItem brokerItem = brokers.get(brokerName);
|
|
||||||
if (brokerItem != null) {
|
|
||||||
return brokerItem.factory;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Connection createConnection(String brokerName) throws Exception {
|
|
||||||
BrokerItem brokerItem = brokers.get(brokerName);
|
|
||||||
if (brokerItem != null) {
|
|
||||||
return brokerItem.createConnection();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MessageConsumer createSyncConsumer(String brokerName, Destination dest) throws Exception {
|
|
||||||
BrokerItem brokerItem = brokers.get(brokerName);
|
|
||||||
if (brokerItem != null) {
|
|
||||||
Connection con = brokerItem.createConnection();
|
|
||||||
con.start();
|
|
||||||
Session sess = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageConsumer consumer = sess.createConsumer(dest);
|
|
||||||
return consumer;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MessageConsumer createConsumer(String brokerName, Destination dest) throws Exception {
|
|
||||||
return createConsumer(brokerName, dest, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MessageConsumer createConsumer(String brokerName,
|
|
||||||
Destination dest,
|
|
||||||
String messageSelector) throws Exception {
|
|
||||||
return createConsumer(brokerName, dest, null, messageSelector);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MessageConsumer createConsumer(String brokerName,
|
|
||||||
Destination dest,
|
|
||||||
CountDownLatch latch) throws Exception {
|
|
||||||
return createConsumer(brokerName, dest, latch, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MessageConsumer createConsumer(String brokerName,
|
|
||||||
Destination dest,
|
|
||||||
CountDownLatch latch,
|
|
||||||
String messageSelector) throws Exception {
|
|
||||||
BrokerItem brokerItem = brokers.get(brokerName);
|
|
||||||
if (brokerItem != null) {
|
|
||||||
return brokerItem.createConsumer(dest, latch, messageSelector);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected QueueBrowser createBrowser(String brokerName, Destination dest) throws Exception {
|
|
||||||
BrokerItem brokerItem = brokers.get(brokerName);
|
|
||||||
if (brokerItem != null) {
|
|
||||||
return brokerItem.createBrowser(dest);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MessageConsumer createDurableSubscriber(String brokerName, Topic dest, String name) throws Exception {
|
|
||||||
BrokerItem brokerItem = brokers.get(brokerName);
|
|
||||||
if (brokerItem != null) {
|
|
||||||
return brokerItem.createDurableSubscriber(dest, name);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MessageIdList getBrokerMessages(String brokerName) {
|
|
||||||
BrokerItem brokerItem = brokers.get(brokerName);
|
|
||||||
if (brokerItem != null) {
|
|
||||||
return brokerItem.getAllMessages();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MessageIdList getConsumerMessages(String brokerName, MessageConsumer consumer) {
|
|
||||||
BrokerItem brokerItem = brokers.get(brokerName);
|
|
||||||
if (brokerItem != null) {
|
|
||||||
return brokerItem.getConsumerMessages(consumer);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void assertConsumersConnect(String brokerName,
|
|
||||||
Destination destination,
|
|
||||||
final int count,
|
|
||||||
long timeout) throws Exception {
|
|
||||||
BrokerItem brokerItem = brokers.get(brokerName);
|
|
||||||
Connection conn = brokerItem.createConnection();
|
|
||||||
conn.start();
|
|
||||||
ConsumerEventSource ces = new ConsumerEventSource(conn, destination);
|
|
||||||
|
|
||||||
try {
|
|
||||||
final AtomicInteger actualConnected = new AtomicInteger();
|
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
|
||||||
ces.setConsumerListener(new ConsumerListener() {
|
|
||||||
@Override
|
|
||||||
public void onConsumerEvent(ConsumerEvent event) {
|
|
||||||
if (actualConnected.get() < count) {
|
|
||||||
actualConnected.set(event.getConsumerCount());
|
|
||||||
}
|
|
||||||
if (event.getConsumerCount() >= count) {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ces.start();
|
|
||||||
|
|
||||||
latch.await(timeout, TimeUnit.MILLISECONDS);
|
|
||||||
assertTrue("Expected at least " + count + " consumers to connect, but only " + actualConnected.get() + " connectect within " + timeout + " ms", actualConnected.get() >= count);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
ces.stop();
|
|
||||||
conn.close();
|
|
||||||
brokerItem.connections.remove(conn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void sendMessages(String brokerName, Destination destination, int count) throws Exception {
|
|
||||||
sendMessages(brokerName, destination, count, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void sendMessages(String brokerName,
|
|
||||||
Destination destination,
|
|
||||||
int count,
|
|
||||||
HashMap<String, Object> properties) throws Exception {
|
|
||||||
BrokerItem brokerItem = brokers.get(brokerName);
|
|
||||||
|
|
||||||
Connection conn = brokerItem.createConnection();
|
|
||||||
conn.start();
|
|
||||||
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
|
|
||||||
MessageProducer producer = brokerItem.createProducer(destination, sess);
|
|
||||||
producer.setDeliveryMode(persistentDelivery ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
TextMessage msg = createTextMessage(sess, conn.getClientID() + ": Message-" + i);
|
|
||||||
if (properties != null) {
|
|
||||||
for (String propertyName : properties.keySet()) {
|
|
||||||
msg.setObjectProperty(propertyName, properties.get(propertyName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
producer.send(msg);
|
|
||||||
onSend(i, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
producer.close();
|
|
||||||
sess.close();
|
|
||||||
conn.close();
|
|
||||||
brokerItem.connections.remove(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onSend(int i, TextMessage msg) {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TextMessage createTextMessage(Session session, String initText) throws Exception {
|
|
||||||
TextMessage msg = session.createTextMessage();
|
|
||||||
|
|
||||||
// Pad message text
|
|
||||||
if (initText.length() < messageSize) {
|
|
||||||
char[] data = new char[messageSize - initText.length()];
|
|
||||||
Arrays.fill(data, '*');
|
|
||||||
String str = new String(data);
|
|
||||||
msg.setText(initText + str);
|
|
||||||
|
|
||||||
// Do not pad message text
|
|
||||||
} else {
|
|
||||||
msg.setText(initText);
|
|
||||||
}
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ActiveMQDestination createDestination(String name, boolean topic) throws JMSException {
|
|
||||||
Destination dest;
|
|
||||||
if (topic) {
|
|
||||||
dest = new ActiveMQTopic(name);
|
|
||||||
destinations.put(name, dest);
|
|
||||||
return (ActiveMQDestination) dest;
|
|
||||||
} else {
|
|
||||||
dest = new ActiveMQQueue(name);
|
|
||||||
destinations.put(name, dest);
|
|
||||||
return (ActiveMQDestination) dest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
brokers = new HashMap<>();
|
|
||||||
destinations = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
destroyAllBrokers();
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void destroyBroker(String brokerName) throws Exception {
|
|
||||||
BrokerItem brokerItem = brokers.remove(brokerName);
|
|
||||||
|
|
||||||
if (brokerItem != null) {
|
|
||||||
brokerItem.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void destroyAllBrokers() throws Exception {
|
|
||||||
for (Iterator<BrokerItem> i = brokers.values().iterator(); i.hasNext(); ) {
|
|
||||||
BrokerItem brokerItem = i.next();
|
|
||||||
brokerItem.destroy();
|
|
||||||
}
|
|
||||||
brokers.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Class to group broker components together
|
|
||||||
public class BrokerItem {
|
|
||||||
|
|
||||||
public BrokerService broker;
|
|
||||||
public ActiveMQConnectionFactory factory;
|
|
||||||
public List<Connection> connections;
|
|
||||||
public Map<MessageConsumer, MessageIdList> consumers;
|
|
||||||
public MessageIdList allMessages = new MessageIdList();
|
|
||||||
public boolean persistent;
|
|
||||||
private IdGenerator id;
|
|
||||||
|
|
||||||
public BrokerItem(BrokerService broker) throws Exception {
|
|
||||||
this.broker = broker;
|
|
||||||
|
|
||||||
factory = new ActiveMQConnectionFactory(broker.getVmConnectorURI());
|
|
||||||
factory.setConnectionIDPrefix(broker.getBrokerName());
|
|
||||||
consumers = Collections.synchronizedMap(new HashMap<MessageConsumer, MessageIdList>());
|
|
||||||
connections = Collections.synchronizedList(new ArrayList<Connection>());
|
|
||||||
allMessages.setVerbose(verbose);
|
|
||||||
id = new IdGenerator(broker.getBrokerName() + ":");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Connection createConnection() throws Exception {
|
|
||||||
Connection conn = factory.createConnection();
|
|
||||||
conn.setClientID(id.generateId());
|
|
||||||
|
|
||||||
connections.add(conn);
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageConsumer createConsumer(Destination dest) throws Exception {
|
|
||||||
return createConsumer(dest, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageConsumer createConsumer(Destination dest, String messageSelector) throws Exception {
|
|
||||||
return createConsumer(dest, null, messageSelector);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageConsumer createConsumer(Destination dest,
|
|
||||||
CountDownLatch latch,
|
|
||||||
String messageSelector) throws Exception {
|
|
||||||
Connection c = createConnection();
|
|
||||||
c.start();
|
|
||||||
Session s = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
return createConsumerWithSession(dest, s, latch, messageSelector);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageConsumer createConsumerWithSession(Destination dest, Session sess) throws Exception {
|
|
||||||
return createConsumerWithSession(dest, sess, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageConsumer createConsumerWithSession(Destination dest,
|
|
||||||
Session sess,
|
|
||||||
CountDownLatch latch,
|
|
||||||
String messageSelector) throws Exception {
|
|
||||||
MessageConsumer client = sess.createConsumer(dest, messageSelector);
|
|
||||||
MessageIdList messageIdList = new MessageIdList();
|
|
||||||
messageIdList.setCountDownLatch(latch);
|
|
||||||
messageIdList.setParent(allMessages);
|
|
||||||
client.setMessageListener(messageIdList);
|
|
||||||
consumers.put(client, messageIdList);
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QueueBrowser createBrowser(Destination dest) throws Exception {
|
|
||||||
Connection c = createConnection();
|
|
||||||
c.start();
|
|
||||||
Session s = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
return s.createBrowser((Queue) dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageConsumer createDurableSubscriber(Topic dest, String name) throws Exception {
|
|
||||||
Connection c = createConnection();
|
|
||||||
c.start();
|
|
||||||
Session s = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
return createDurableSubscriber(dest, s, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageConsumer createDurableSubscriber(Topic dest, Session sess, String name) throws Exception {
|
|
||||||
MessageConsumer client = sess.createDurableSubscriber(dest, name);
|
|
||||||
MessageIdList messageIdList = new MessageIdList();
|
|
||||||
messageIdList.setParent(allMessages);
|
|
||||||
client.setMessageListener(messageIdList);
|
|
||||||
consumers.put(client, messageIdList);
|
|
||||||
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageIdList getAllMessages() {
|
|
||||||
return allMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageIdList getConsumerMessages(MessageConsumer consumer) {
|
|
||||||
return consumers.get(consumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageProducer createProducer(Destination dest) throws Exception {
|
|
||||||
Connection c = createConnection();
|
|
||||||
c.start();
|
|
||||||
Session s = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
return createProducer(dest, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageProducer createProducer(Destination dest, Session sess) throws Exception {
|
|
||||||
MessageProducer client = sess.createProducer(dest);
|
|
||||||
client.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void destroy() throws Exception {
|
|
||||||
while (!connections.isEmpty()) {
|
|
||||||
Connection c = connections.remove(0);
|
|
||||||
try {
|
|
||||||
c.close();
|
|
||||||
} catch (ConnectionClosedException e) {
|
|
||||||
} catch (JMSException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
broker.stop();
|
|
||||||
broker.waitUntilStopped();
|
|
||||||
consumers.clear();
|
|
||||||
|
|
||||||
broker = null;
|
|
||||||
connections = null;
|
|
||||||
consumers = null;
|
|
||||||
factory = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,168 +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;
|
|
||||||
|
|
||||||
import javax.jms.BytesMessage;
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
import javax.jms.DeliveryMode;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.Topic;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerFactory;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Small burn test moves sends a moderate amount of messages through the broker,
|
|
||||||
* to checking to make sure that the broker does not lock up after a while of
|
|
||||||
* sustained messaging.
|
|
||||||
*/
|
|
||||||
public class LoadTestBurnIn extends JmsTestSupport {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(LoadTestBurnIn.class);
|
|
||||||
|
|
||||||
public ActiveMQDestination destination;
|
|
||||||
public int deliveryMode;
|
|
||||||
public byte destinationType;
|
|
||||||
public boolean durableConsumer;
|
|
||||||
public int messageCount = 50000;
|
|
||||||
public int messageSize = 1024;
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(LoadTestBurnIn.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
LOG.info("Start: " + getName());
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
try {
|
|
||||||
super.tearDown();
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace(System.out);
|
|
||||||
} finally {
|
|
||||||
LOG.info("End: " + getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(suite());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
return BrokerFactory.createBroker(new URI("broker://(tcp://localhost:0)?useJmx=true"));
|
|
||||||
// return BrokerFactory.createBroker(new
|
|
||||||
// URI("xbean:org/apache/activemq/broker/store/loadtester.xml"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ConnectionFactory createConnectionFactory() throws URISyntaxException, IOException {
|
|
||||||
return new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getServer().getConnectURI());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initCombosForTestSendReceive() {
|
|
||||||
addCombinationValues("deliveryMode", new Object[]{Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
|
||||||
addCombinationValues("destinationType", new Object[]{Byte.valueOf(ActiveMQDestination.TOPIC_TYPE)});
|
|
||||||
addCombinationValues("durableConsumer", new Object[]{Boolean.TRUE});
|
|
||||||
addCombinationValues("messageSize", new Object[]{Integer.valueOf(101), Integer.valueOf(102), Integer.valueOf(103), Integer.valueOf(104), Integer.valueOf(105), Integer.valueOf(106), Integer.valueOf(107), Integer.valueOf(108)});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSendReceive() throws Exception {
|
|
||||||
|
|
||||||
// Durable consumer combination is only valid with topics
|
|
||||||
if (durableConsumer && destinationType != ActiveMQDestination.TOPIC_TYPE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
connection.setClientID(getName());
|
|
||||||
connection.getPrefetchPolicy().setAll(1000);
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
destination = createDestination(session, destinationType);
|
|
||||||
MessageConsumer consumer;
|
|
||||||
if (durableConsumer) {
|
|
||||||
consumer = session.createDurableSubscriber((Topic) destination, "sub1:" + System.currentTimeMillis());
|
|
||||||
} else {
|
|
||||||
consumer = session.createConsumer(destination);
|
|
||||||
}
|
|
||||||
profilerPause("Ready: ");
|
|
||||||
|
|
||||||
final CountDownLatch producerDoneLatch = new CountDownLatch(1);
|
|
||||||
|
|
||||||
// Send the messages, async
|
|
||||||
new Thread() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Connection connection2 = null;
|
|
||||||
try {
|
|
||||||
connection2 = factory.createConnection();
|
|
||||||
Session session = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageProducer producer = session.createProducer(destination);
|
|
||||||
producer.setDeliveryMode(deliveryMode);
|
|
||||||
for (int i = 0; i < messageCount; i++) {
|
|
||||||
BytesMessage m = session.createBytesMessage();
|
|
||||||
m.writeBytes(new byte[messageSize]);
|
|
||||||
producer.send(m);
|
|
||||||
}
|
|
||||||
producer.close();
|
|
||||||
} catch (JMSException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
safeClose(connection2);
|
|
||||||
producerDoneLatch.countDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
|
|
||||||
// Make sure all the messages were delivered.
|
|
||||||
Message message = null;
|
|
||||||
for (int i = 0; i < messageCount; i++) {
|
|
||||||
message = consumer.receive(5000);
|
|
||||||
assertNotNull("Did not get message: " + i, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
profilerPause("Done: ");
|
|
||||||
|
|
||||||
assertNull(consumer.receiveNoWait());
|
|
||||||
message.acknowledge();
|
|
||||||
|
|
||||||
// Make sure the producer thread finishes.
|
|
||||||
assertTrue(producerDoneLatch.await(5, TimeUnit.SECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,63 +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;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.springframework.context.support.AbstractApplicationContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A useful base class for spring based unit test cases
|
|
||||||
*/
|
|
||||||
public abstract class SpringTestSupport extends TestCase {
|
|
||||||
|
|
||||||
protected AbstractApplicationContext context;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
context = createApplicationContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract AbstractApplicationContext createApplicationContext();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
if (context != null) {
|
|
||||||
context.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Object getBean(String name) {
|
|
||||||
Object bean = context.getBean(name);
|
|
||||||
if (bean == null) {
|
|
||||||
fail("Should have found bean named '" + name + "' in the Spring ApplicationContext");
|
|
||||||
}
|
|
||||||
return bean;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void assertSetEquals(String description, Object[] expected, Set<?> actual) {
|
|
||||||
Set<Object> expectedSet = new HashSet<>();
|
|
||||||
expectedSet.addAll(Arrays.asList(expected));
|
|
||||||
assertEquals(description, expectedSet, actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -35,7 +35,6 @@ import org.apache.activemq.command.ActiveMQTopic;
|
||||||
import org.apache.activemq.store.PersistenceAdapter;
|
import org.apache.activemq.store.PersistenceAdapter;
|
||||||
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
||||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
||||||
import org.apache.activemq.store.leveldb.LevelDBPersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.memory.MemoryPersistenceAdapter;
|
import org.apache.activemq.store.memory.MemoryPersistenceAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -168,7 +167,7 @@ public abstract class TestSupport extends CombinationTestSupport {
|
||||||
return destination.isQueue() ? regionBroker.getQueueRegion().getDestinationMap() : regionBroker.getTopicRegion().getDestinationMap();
|
return destination.isQueue() ? regionBroker.getQueueRegion().getDestinationMap() : regionBroker.getTopicRegion().getDestinationMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum PersistenceAdapterChoice {LevelDB, KahaDB, AMQ, JDBC, MEM}
|
public static enum PersistenceAdapterChoice {KahaDB, AMQ, JDBC, MEM}
|
||||||
|
|
||||||
public PersistenceAdapter setDefaultPersistenceAdapter(BrokerService broker) throws IOException {
|
public PersistenceAdapter setDefaultPersistenceAdapter(BrokerService broker) throws IOException {
|
||||||
return setPersistenceAdapter(broker, defaultPersistenceAdapter);
|
return setPersistenceAdapter(broker, defaultPersistenceAdapter);
|
||||||
|
@ -186,9 +185,6 @@ public abstract class TestSupport extends CombinationTestSupport {
|
||||||
case KahaDB:
|
case KahaDB:
|
||||||
adapter = new KahaDBPersistenceAdapter();
|
adapter = new KahaDBPersistenceAdapter();
|
||||||
break;
|
break;
|
||||||
case LevelDB:
|
|
||||||
adapter = new LevelDBPersistenceAdapter();
|
|
||||||
break;
|
|
||||||
case MEM:
|
case MEM:
|
||||||
adapter = new MemoryPersistenceAdapter();
|
adapter = new MemoryPersistenceAdapter();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.apache.activemq.command.ActiveMQDestination;
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
import org.apache.activemq.command.ActiveMQQueue;
|
||||||
import org.apache.activemq.command.ConsumerControl;
|
import org.apache.activemq.command.ConsumerControl;
|
||||||
import org.apache.activemq.command.ExceptionResponse;
|
import org.apache.activemq.command.ExceptionResponse;
|
||||||
import org.apache.activemq.spring.SpringConsumer;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -54,9 +53,8 @@ public class ZeroPrefetchConsumerTest extends EmbeddedBrokerTestSupport {
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||||
MessageConsumer consumer = session.createConsumer(queue);
|
MessageConsumer consumer = session.createConsumer(queue);
|
||||||
|
|
||||||
MessageListener listener = new SpringConsumer();
|
|
||||||
try {
|
try {
|
||||||
consumer.setMessageListener(listener);
|
consumer.setMessageListener(msg -> {});
|
||||||
fail("Should have thrown JMSException as we cannot use MessageListener with zero prefetch");
|
fail("Should have thrown JMSException as we cannot use MessageListener with zero prefetch");
|
||||||
} catch (JMSException e) {
|
} catch (JMSException e) {
|
||||||
LOG.info("Received expected exception : " + e);
|
LOG.info("Received expected exception : " + e);
|
||||||
|
|
|
@ -1,226 +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.advisory;
|
|
||||||
|
|
||||||
import javax.jms.BytesMessage;
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageListener;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Queue;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TemporaryQueue;
|
|
||||||
import javax.jms.Topic;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.policy.ConstantPendingMessageLimitStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQMessage;
|
|
||||||
|
|
||||||
public class AdvisoryTempDestinationTests extends TestCase {
|
|
||||||
|
|
||||||
protected static final int MESSAGE_COUNT = 2000;
|
|
||||||
protected BrokerService broker;
|
|
||||||
protected Connection connection;
|
|
||||||
protected String bindAddress = ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL;
|
|
||||||
protected int topicCount;
|
|
||||||
|
|
||||||
public void testNoSlowConsumerAdvisory() throws Exception {
|
|
||||||
Session s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
TemporaryQueue queue = s.createTemporaryQueue();
|
|
||||||
MessageConsumer consumer = s.createConsumer(queue);
|
|
||||||
consumer.setMessageListener(new MessageListener() {
|
|
||||||
@Override
|
|
||||||
public void onMessage(Message message) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getSlowConsumerAdvisoryTopic((ActiveMQDestination) queue);
|
|
||||||
s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageConsumer advisoryConsumer = s.createConsumer(advisoryTopic);
|
|
||||||
// start throwing messages at the consumer
|
|
||||||
MessageProducer producer = s.createProducer(queue);
|
|
||||||
for (int i = 0; i < MESSAGE_COUNT; i++) {
|
|
||||||
BytesMessage m = s.createBytesMessage();
|
|
||||||
m.writeBytes(new byte[1024]);
|
|
||||||
producer.send(m);
|
|
||||||
}
|
|
||||||
Message msg = advisoryConsumer.receive(1000);
|
|
||||||
assertNull(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSlowConsumerAdvisory() throws Exception {
|
|
||||||
Session s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
TemporaryQueue queue = s.createTemporaryQueue();
|
|
||||||
MessageConsumer consumer = s.createConsumer(queue);
|
|
||||||
assertNotNull(consumer);
|
|
||||||
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getSlowConsumerAdvisoryTopic((ActiveMQDestination) queue);
|
|
||||||
s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageConsumer advisoryConsumer = s.createConsumer(advisoryTopic);
|
|
||||||
// start throwing messages at the consumer
|
|
||||||
MessageProducer producer = s.createProducer(queue);
|
|
||||||
for (int i = 0; i < MESSAGE_COUNT; i++) {
|
|
||||||
BytesMessage m = s.createBytesMessage();
|
|
||||||
m.writeBytes(new byte[1024]);
|
|
||||||
producer.send(m);
|
|
||||||
}
|
|
||||||
Message msg = advisoryConsumer.receive(1000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMessageDeliveryAdvisory() throws Exception {
|
|
||||||
Session s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
TemporaryQueue queue = s.createTemporaryQueue();
|
|
||||||
MessageConsumer consumer = s.createConsumer(queue);
|
|
||||||
assertNotNull(consumer);
|
|
||||||
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getMessageDeliveredAdvisoryTopic((ActiveMQDestination) queue);
|
|
||||||
MessageConsumer advisoryConsumer = s.createConsumer(advisoryTopic);
|
|
||||||
//start throwing messages at the consumer
|
|
||||||
MessageProducer producer = s.createProducer(queue);
|
|
||||||
|
|
||||||
BytesMessage m = s.createBytesMessage();
|
|
||||||
m.writeBytes(new byte[1024]);
|
|
||||||
producer.send(m);
|
|
||||||
|
|
||||||
Message msg = advisoryConsumer.receive(1000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testTempMessageConsumedAdvisory() throws Exception {
|
|
||||||
Session s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
TemporaryQueue queue = s.createTemporaryQueue();
|
|
||||||
MessageConsumer consumer = s.createConsumer(queue);
|
|
||||||
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getMessageConsumedAdvisoryTopic((ActiveMQDestination) queue);
|
|
||||||
MessageConsumer advisoryConsumer = s.createConsumer(advisoryTopic);
|
|
||||||
//start throwing messages at the consumer
|
|
||||||
MessageProducer producer = s.createProducer(queue);
|
|
||||||
|
|
||||||
BytesMessage m = s.createBytesMessage();
|
|
||||||
m.writeBytes(new byte[1024]);
|
|
||||||
producer.send(m);
|
|
||||||
String id = m.getJMSMessageID();
|
|
||||||
Message msg = consumer.receive(1000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
|
|
||||||
msg = advisoryConsumer.receive(1000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
|
|
||||||
ActiveMQMessage message = (ActiveMQMessage) msg;
|
|
||||||
ActiveMQMessage payload = (ActiveMQMessage) message.getDataStructure();
|
|
||||||
String originalId = payload.getJMSMessageID();
|
|
||||||
assertEquals(originalId, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMessageExpiredAdvisory() throws Exception {
|
|
||||||
Session s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
Queue queue = s.createQueue(getClass().getName());
|
|
||||||
MessageConsumer consumer = s.createConsumer(queue);
|
|
||||||
assertNotNull(consumer);
|
|
||||||
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getExpiredMessageTopic((ActiveMQDestination) queue);
|
|
||||||
MessageConsumer advisoryConsumer = s.createConsumer(advisoryTopic);
|
|
||||||
//start throwing messages at the consumer
|
|
||||||
MessageProducer producer = s.createProducer(queue);
|
|
||||||
producer.setTimeToLive(1);
|
|
||||||
for (int i = 0; i < MESSAGE_COUNT; i++) {
|
|
||||||
BytesMessage m = s.createBytesMessage();
|
|
||||||
m.writeBytes(new byte[1024]);
|
|
||||||
producer.send(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
Message msg = advisoryConsumer.receive(5000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
if (broker == null) {
|
|
||||||
broker = createBroker();
|
|
||||||
}
|
|
||||||
ConnectionFactory factory = createConnectionFactory();
|
|
||||||
connection = factory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
connection.close();
|
|
||||||
if (broker != null) {
|
|
||||||
broker.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_BROKER_URL);
|
|
||||||
return cf;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService answer = new BrokerService();
|
|
||||||
configureBroker(answer);
|
|
||||||
answer.start();
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void configureBroker(BrokerService answer) throws Exception {
|
|
||||||
answer.setPersistent(false);
|
|
||||||
ConstantPendingMessageLimitStrategy strategy = new ConstantPendingMessageLimitStrategy();
|
|
||||||
strategy.setLimit(10);
|
|
||||||
PolicyEntry tempQueueEntry = createPolicyEntry(strategy);
|
|
||||||
tempQueueEntry.setTempQueue(true);
|
|
||||||
PolicyEntry tempTopicEntry = createPolicyEntry(strategy);
|
|
||||||
tempTopicEntry.setTempTopic(true);
|
|
||||||
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
final List<PolicyEntry> policyEntries = new ArrayList<>();
|
|
||||||
policyEntries.add(tempQueueEntry);
|
|
||||||
policyEntries.add(tempTopicEntry);
|
|
||||||
pMap.setPolicyEntries(policyEntries);
|
|
||||||
|
|
||||||
answer.setDestinationPolicy(pMap);
|
|
||||||
answer.addConnector(bindAddress);
|
|
||||||
answer.setDeleteAllMessagesOnStartup(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private PolicyEntry createPolicyEntry(ConstantPendingMessageLimitStrategy strategy) {
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
policy.setAdvisoryForFastProducers(true);
|
|
||||||
policy.setAdvisoryForConsumed(true);
|
|
||||||
policy.setAdvisoryForDelivery(true);
|
|
||||||
policy.setAdvisoryForDiscardingMessages(true);
|
|
||||||
policy.setAdvisoryForSlowConsumers(true);
|
|
||||||
policy.setAdvisoryWhenFull(true);
|
|
||||||
policy.setProducerFlowControl(false);
|
|
||||||
policy.setPendingMessageLimitStrategy(strategy);
|
|
||||||
|
|
||||||
return policy;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,234 +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.advisory;
|
|
||||||
|
|
||||||
import javax.jms.BytesMessage;
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageListener;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Queue;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.Topic;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.ActiveMQPrefetchPolicy;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.policy.ConstantPendingMessageLimitStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQMessage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class AdvisoryTests extends TestCase {
|
|
||||||
|
|
||||||
protected static final int MESSAGE_COUNT = 2000;
|
|
||||||
protected BrokerService broker;
|
|
||||||
protected Connection connection;
|
|
||||||
protected String bindAddress = ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL;
|
|
||||||
protected int topicCount;
|
|
||||||
|
|
||||||
public void testNoSlowConsumerAdvisory() throws Exception {
|
|
||||||
Session s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
Queue queue = s.createQueue(getClass().getName());
|
|
||||||
MessageConsumer consumer = s.createConsumer(queue);
|
|
||||||
consumer.setMessageListener(new MessageListener() {
|
|
||||||
@Override
|
|
||||||
public void onMessage(Message message) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getSlowConsumerAdvisoryTopic((ActiveMQDestination) queue);
|
|
||||||
s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageConsumer advisoryConsumer = s.createConsumer(advisoryTopic);
|
|
||||||
// start throwing messages at the consumer
|
|
||||||
MessageProducer producer = s.createProducer(queue);
|
|
||||||
for (int i = 0; i < MESSAGE_COUNT; i++) {
|
|
||||||
BytesMessage m = s.createBytesMessage();
|
|
||||||
m.writeBytes(new byte[1024]);
|
|
||||||
producer.send(m);
|
|
||||||
}
|
|
||||||
Message msg = advisoryConsumer.receive(1000);
|
|
||||||
assertNull(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSlowConsumerAdvisory() throws Exception {
|
|
||||||
Session s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
Queue queue = s.createQueue(getClass().getName());
|
|
||||||
MessageConsumer consumer = s.createConsumer(queue);
|
|
||||||
assertNotNull(consumer);
|
|
||||||
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getSlowConsumerAdvisoryTopic((ActiveMQDestination) queue);
|
|
||||||
s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageConsumer advisoryConsumer = s.createConsumer(advisoryTopic);
|
|
||||||
// start throwing messages at the consumer
|
|
||||||
MessageProducer producer = s.createProducer(queue);
|
|
||||||
for (int i = 0; i < MESSAGE_COUNT; i++) {
|
|
||||||
BytesMessage m = s.createBytesMessage();
|
|
||||||
m.writeBytes(new byte[1024]);
|
|
||||||
producer.send(m);
|
|
||||||
}
|
|
||||||
Message msg = advisoryConsumer.receive(1000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMessageDeliveryAdvisory() throws Exception {
|
|
||||||
Session s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
Queue queue = s.createQueue(getClass().getName());
|
|
||||||
MessageConsumer consumer = s.createConsumer(queue);
|
|
||||||
assertNotNull(consumer);
|
|
||||||
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getMessageDeliveredAdvisoryTopic((ActiveMQDestination) queue);
|
|
||||||
MessageConsumer advisoryConsumer = s.createConsumer(advisoryTopic);
|
|
||||||
//start throwing messages at the consumer
|
|
||||||
MessageProducer producer = s.createProducer(queue);
|
|
||||||
|
|
||||||
BytesMessage m = s.createBytesMessage();
|
|
||||||
m.writeBytes(new byte[1024]);
|
|
||||||
producer.send(m);
|
|
||||||
|
|
||||||
Message msg = advisoryConsumer.receive(1000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMessageConsumedAdvisory() throws Exception {
|
|
||||||
Session s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
Queue queue = s.createQueue(getClass().getName());
|
|
||||||
MessageConsumer consumer = s.createConsumer(queue);
|
|
||||||
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getMessageConsumedAdvisoryTopic((ActiveMQDestination) queue);
|
|
||||||
MessageConsumer advisoryConsumer = s.createConsumer(advisoryTopic);
|
|
||||||
//start throwing messages at the consumer
|
|
||||||
MessageProducer producer = s.createProducer(queue);
|
|
||||||
|
|
||||||
BytesMessage m = s.createBytesMessage();
|
|
||||||
m.writeBytes(new byte[1024]);
|
|
||||||
producer.send(m);
|
|
||||||
String id = m.getJMSMessageID();
|
|
||||||
Message msg = consumer.receive(1000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
|
|
||||||
msg = advisoryConsumer.receive(1000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
|
|
||||||
ActiveMQMessage message = (ActiveMQMessage) msg;
|
|
||||||
ActiveMQMessage payload = (ActiveMQMessage) message.getDataStructure();
|
|
||||||
String originalId = payload.getJMSMessageID();
|
|
||||||
assertEquals(originalId, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMessageExpiredAdvisory() throws Exception {
|
|
||||||
Session s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
Queue queue = s.createQueue(getClass().getName());
|
|
||||||
MessageConsumer consumer = s.createConsumer(queue);
|
|
||||||
assertNotNull(consumer);
|
|
||||||
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getExpiredMessageTopic((ActiveMQDestination) queue);
|
|
||||||
MessageConsumer advisoryConsumer = s.createConsumer(advisoryTopic);
|
|
||||||
//start throwing messages at the consumer
|
|
||||||
MessageProducer producer = s.createProducer(queue);
|
|
||||||
producer.setTimeToLive(1);
|
|
||||||
for (int i = 0; i < MESSAGE_COUNT; i++) {
|
|
||||||
BytesMessage m = s.createBytesMessage();
|
|
||||||
m.writeBytes(new byte[1024]);
|
|
||||||
producer.send(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
Message msg = advisoryConsumer.receive(2000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void xtestMessageDiscardedAdvisory() throws Exception {
|
|
||||||
Session s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
Topic topic = s.createTopic(getClass().getName());
|
|
||||||
MessageConsumer consumer = s.createConsumer(topic);
|
|
||||||
assertNotNull(consumer);
|
|
||||||
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getMessageDiscardedAdvisoryTopic((ActiveMQDestination) topic);
|
|
||||||
MessageConsumer advisoryConsumer = s.createConsumer(advisoryTopic);
|
|
||||||
//start throwing messages at the consumer
|
|
||||||
MessageProducer producer = s.createProducer(topic);
|
|
||||||
int count = (new ActiveMQPrefetchPolicy().getTopicPrefetch() * 2);
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
BytesMessage m = s.createBytesMessage();
|
|
||||||
producer.send(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
Message msg = advisoryConsumer.receive(1000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
if (broker == null) {
|
|
||||||
broker = createBroker();
|
|
||||||
}
|
|
||||||
ConnectionFactory factory = createConnectionFactory();
|
|
||||||
connection = factory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
connection.close();
|
|
||||||
if (broker != null) {
|
|
||||||
broker.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_BROKER_URL);
|
|
||||||
return cf;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService answer = new BrokerService();
|
|
||||||
configureBroker(answer);
|
|
||||||
answer.start();
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void configureBroker(BrokerService answer) throws Exception {
|
|
||||||
answer.setPersistent(false);
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
policy.setAdvisoryForFastProducers(true);
|
|
||||||
policy.setAdvisoryForConsumed(true);
|
|
||||||
policy.setAdvisoryForDelivery(true);
|
|
||||||
policy.setAdvisoryForDiscardingMessages(true);
|
|
||||||
policy.setAdvisoryForSlowConsumers(true);
|
|
||||||
policy.setAdvisoryWhenFull(true);
|
|
||||||
policy.setProducerFlowControl(false);
|
|
||||||
ConstantPendingMessageLimitStrategy strategy = new ConstantPendingMessageLimitStrategy();
|
|
||||||
strategy.setLimit(10);
|
|
||||||
policy.setPendingMessageLimitStrategy(strategy);
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
|
|
||||||
answer.setDestinationPolicy(pMap);
|
|
||||||
answer.addConnector(bindAddress);
|
|
||||||
answer.setDeleteAllMessagesOnStartup(true);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,156 +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.advisory;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageListener;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ConsumerListenerTest extends EmbeddedBrokerTestSupport implements ConsumerListener {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ConsumerListenerTest.class);
|
|
||||||
|
|
||||||
protected Session consumerSession1;
|
|
||||||
protected Session consumerSession2;
|
|
||||||
protected int consumerCounter;
|
|
||||||
protected ConsumerEventSource consumerEventSource;
|
|
||||||
protected BlockingQueue<ConsumerEvent> eventQueue = new ArrayBlockingQueue<>(1000);
|
|
||||||
private Connection connection;
|
|
||||||
|
|
||||||
public void testConsumerEvents() throws Exception {
|
|
||||||
consumerEventSource.start();
|
|
||||||
|
|
||||||
consumerSession1 = createConsumer();
|
|
||||||
assertConsumerEvent(1, true);
|
|
||||||
|
|
||||||
consumerSession2 = createConsumer();
|
|
||||||
assertConsumerEvent(2, true);
|
|
||||||
|
|
||||||
consumerSession1.close();
|
|
||||||
consumerSession1 = null;
|
|
||||||
assertConsumerEvent(1, false);
|
|
||||||
|
|
||||||
consumerSession2.close();
|
|
||||||
consumerSession2 = null;
|
|
||||||
assertConsumerEvent(0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testListenWhileAlreadyConsumersActive() throws Exception {
|
|
||||||
consumerSession1 = createConsumer();
|
|
||||||
consumerSession2 = createConsumer();
|
|
||||||
|
|
||||||
consumerEventSource.start();
|
|
||||||
assertConsumerEvent(2, true);
|
|
||||||
assertConsumerEvent(2, true);
|
|
||||||
|
|
||||||
consumerSession1.close();
|
|
||||||
consumerSession1 = null;
|
|
||||||
assertConsumerEvent(1, false);
|
|
||||||
|
|
||||||
consumerSession2.close();
|
|
||||||
consumerSession2 = null;
|
|
||||||
assertConsumerEvent(0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testConsumerEventsOnTemporaryDestination() throws Exception {
|
|
||||||
|
|
||||||
Session s = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
Destination dest = useTopic ? s.createTemporaryTopic() : s.createTemporaryQueue();
|
|
||||||
consumerEventSource = new ConsumerEventSource(connection, dest);
|
|
||||||
consumerEventSource.setConsumerListener(this);
|
|
||||||
consumerEventSource.start();
|
|
||||||
MessageConsumer consumer = s.createConsumer(dest);
|
|
||||||
assertConsumerEvent(1, true);
|
|
||||||
consumer.close();
|
|
||||||
assertConsumerEvent(0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConsumerEvent(ConsumerEvent event) {
|
|
||||||
eventQueue.add(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
|
|
||||||
connection = createConnection();
|
|
||||||
connection.start();
|
|
||||||
consumerEventSource = new ConsumerEventSource(connection, destination);
|
|
||||||
consumerEventSource.setConsumerListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
if (consumerEventSource != null) {
|
|
||||||
consumerEventSource.stop();
|
|
||||||
}
|
|
||||||
if (consumerSession2 != null) {
|
|
||||||
consumerSession2.close();
|
|
||||||
}
|
|
||||||
if (consumerSession1 != null) {
|
|
||||||
consumerSession1.close();
|
|
||||||
}
|
|
||||||
if (connection != null) {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void assertConsumerEvent(int count, boolean started) throws InterruptedException {
|
|
||||||
ConsumerEvent event = waitForConsumerEvent();
|
|
||||||
assertEquals("Consumer count", count, event.getConsumerCount());
|
|
||||||
assertEquals("started", started, event.isStarted());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Session createConsumer() throws JMSException {
|
|
||||||
final String consumerText = "Consumer: " + (++consumerCounter);
|
|
||||||
LOG.info("Creating consumer: " + consumerText + " on destination: " + destination);
|
|
||||||
|
|
||||||
Session answer = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageConsumer consumer = answer.createConsumer(destination);
|
|
||||||
consumer.setMessageListener(new MessageListener() {
|
|
||||||
@Override
|
|
||||||
public void onMessage(Message message) {
|
|
||||||
LOG.info("Received message by: " + consumerText + " message: " + message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ConsumerEvent waitForConsumerEvent() throws InterruptedException {
|
|
||||||
ConsumerEvent answer = eventQueue.poll(100000, TimeUnit.MILLISECONDS);
|
|
||||||
assertTrue("Should have received a consumer event!", answer != null);
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,129 +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.advisory;
|
|
||||||
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TextMessage;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
|
||||||
import static org.hamcrest.Matchers.isIn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DestinationListenerTest extends EmbeddedBrokerTestSupport implements DestinationListener {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(DestinationListenerTest.class);
|
|
||||||
protected ActiveMQConnection connection;
|
|
||||||
protected ActiveMQQueue sampleQueue = new ActiveMQQueue("foo.bar");
|
|
||||||
protected ActiveMQTopic sampleTopic = new ActiveMQTopic("cheese");
|
|
||||||
protected List<ActiveMQDestination> newDestinations = new ArrayList<>();
|
|
||||||
|
|
||||||
public void testDestiationSourceHasInitialDestinations() throws Exception {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
|
|
||||||
DestinationSource destinationSource = connection.getDestinationSource();
|
|
||||||
Set<ActiveMQQueue> queues = destinationSource.getQueues();
|
|
||||||
Set<ActiveMQTopic> topics = destinationSource.getTopics();
|
|
||||||
|
|
||||||
LOG.info("Queues: " + queues);
|
|
||||||
LOG.info("Topics: " + topics);
|
|
||||||
|
|
||||||
assertTrue("The queues should not be empty!", !queues.isEmpty());
|
|
||||||
assertTrue("The topics should not be empty!", !topics.isEmpty());
|
|
||||||
|
|
||||||
assertTrue("queues contains initial queue: " + queues, queues.contains(sampleQueue));
|
|
||||||
assertTrue("topics contains initial topic: " + queues, topics.contains(sampleTopic));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testConsumerForcesNotificationOfNewDestination() throws Exception {
|
|
||||||
// now lets cause a destination to be created
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
ActiveMQQueue newQueue = new ActiveMQQueue("Test.Cheese");
|
|
||||||
session.createConsumer(newQueue);
|
|
||||||
|
|
||||||
Thread.sleep(3000);
|
|
||||||
|
|
||||||
assertThat(newQueue, isIn(newDestinations));
|
|
||||||
|
|
||||||
LOG.info("New destinations are: " + newDestinations);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testProducerForcesNotificationOfNewDestination() throws Exception {
|
|
||||||
// now lets cause a destination to be created
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
ActiveMQQueue newQueue = new ActiveMQQueue("Test.Beer");
|
|
||||||
MessageProducer producer = session.createProducer(newQueue);
|
|
||||||
TextMessage message = session.createTextMessage("<hello>world</hello>");
|
|
||||||
producer.send(message);
|
|
||||||
|
|
||||||
Thread.sleep(3000);
|
|
||||||
|
|
||||||
assertThat(newQueue, isIn(newDestinations));
|
|
||||||
|
|
||||||
LOG.info("New destinations are: " + newDestinations);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestinationEvent(DestinationEvent event) {
|
|
||||||
ActiveMQDestination destination = event.getDestination();
|
|
||||||
if (event.isAddOperation()) {
|
|
||||||
LOG.info("Added: " + destination);
|
|
||||||
newDestinations.add(destination);
|
|
||||||
} else {
|
|
||||||
LOG.info("Removed: " + destination);
|
|
||||||
newDestinations.remove(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
|
|
||||||
connection = (ActiveMQConnection) createConnection();
|
|
||||||
connection.start();
|
|
||||||
connection.getDestinationSource().setDestinationListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
broker.setDestinations(new ActiveMQDestination[]{sampleQueue, sampleTopic});
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
if (connection != null) {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,150 +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.advisory;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ProducerListenerTest extends EmbeddedBrokerTestSupport implements ProducerListener {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ProducerListenerTest.class);
|
|
||||||
|
|
||||||
protected Session consumerSession1;
|
|
||||||
protected Session consumerSession2;
|
|
||||||
protected int consumerCounter;
|
|
||||||
protected ProducerEventSource producerEventSource;
|
|
||||||
protected BlockingQueue<ProducerEvent> eventQueue = new ArrayBlockingQueue<>(1000);
|
|
||||||
private Connection connection;
|
|
||||||
|
|
||||||
public void testProducerEvents() throws Exception {
|
|
||||||
producerEventSource.start();
|
|
||||||
|
|
||||||
consumerSession1 = createProducer();
|
|
||||||
assertProducerEvent(1, true);
|
|
||||||
|
|
||||||
consumerSession2 = createProducer();
|
|
||||||
assertProducerEvent(2, true);
|
|
||||||
|
|
||||||
consumerSession1.close();
|
|
||||||
consumerSession1 = null;
|
|
||||||
assertProducerEvent(1, false);
|
|
||||||
|
|
||||||
consumerSession2.close();
|
|
||||||
consumerSession2 = null;
|
|
||||||
assertProducerEvent(0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testListenWhileAlreadyConsumersActive() throws Exception {
|
|
||||||
consumerSession1 = createProducer();
|
|
||||||
consumerSession2 = createProducer();
|
|
||||||
|
|
||||||
producerEventSource.start();
|
|
||||||
assertProducerEvent(2, true);
|
|
||||||
assertProducerEvent(2, true);
|
|
||||||
|
|
||||||
consumerSession1.close();
|
|
||||||
consumerSession1 = null;
|
|
||||||
assertProducerEvent(1, false);
|
|
||||||
|
|
||||||
consumerSession2.close();
|
|
||||||
consumerSession2 = null;
|
|
||||||
assertProducerEvent(0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testConsumerEventsOnTemporaryDestination() throws Exception {
|
|
||||||
|
|
||||||
Session s = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
Destination dest = useTopic ? s.createTemporaryTopic() : s.createTemporaryQueue();
|
|
||||||
producerEventSource = new ProducerEventSource(connection, dest);
|
|
||||||
producerEventSource.setProducerListener(this);
|
|
||||||
producerEventSource.start();
|
|
||||||
MessageProducer producer = s.createProducer(dest);
|
|
||||||
assertProducerEvent(1, true);
|
|
||||||
producer.close();
|
|
||||||
assertProducerEvent(0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProducerEvent(ProducerEvent event) {
|
|
||||||
eventQueue.add(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
|
|
||||||
connection = createConnection();
|
|
||||||
connection.start();
|
|
||||||
producerEventSource = new ProducerEventSource(connection, destination);
|
|
||||||
producerEventSource.setProducerListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
if (producerEventSource != null) {
|
|
||||||
producerEventSource.stop();
|
|
||||||
}
|
|
||||||
if (consumerSession2 != null) {
|
|
||||||
consumerSession2.close();
|
|
||||||
}
|
|
||||||
if (consumerSession1 != null) {
|
|
||||||
consumerSession1.close();
|
|
||||||
}
|
|
||||||
if (connection != null) {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void assertProducerEvent(int count, boolean started) throws InterruptedException {
|
|
||||||
ProducerEvent event = waitForProducerEvent();
|
|
||||||
assertEquals("Producer count", count, event.getProducerCount());
|
|
||||||
assertEquals("started", started, event.isStarted());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Session createProducer() throws JMSException {
|
|
||||||
final String consumerText = "Consumer: " + (++consumerCounter);
|
|
||||||
LOG.info("Creating consumer: " + consumerText + " on destination: " + destination);
|
|
||||||
|
|
||||||
Session answer = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageProducer producer = answer.createProducer(destination);
|
|
||||||
assertNotNull(producer);
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ProducerEvent waitForProducerEvent() throws InterruptedException {
|
|
||||||
ProducerEvent answer = eventQueue.poll(100000, TimeUnit.MILLISECONDS);
|
|
||||||
assertTrue("Should have received a consumer event!", answer != null);
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,152 +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.advisory;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageListener;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.Topic;
|
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
import org.apache.activemq.broker.region.RegionBroker;
|
|
||||||
import org.apache.activemq.command.ActiveMQTempQueue;
|
|
||||||
import org.apache.activemq.command.ActiveMQTempTopic;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class TempDestDeleteTest extends EmbeddedBrokerTestSupport implements ConsumerListener {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(TempDestDeleteTest.class);
|
|
||||||
|
|
||||||
protected int consumerCounter;
|
|
||||||
protected ConsumerEventSource topicConsumerEventSource;
|
|
||||||
protected BlockingQueue<ConsumerEvent> eventQueue = new ArrayBlockingQueue<>(1000);
|
|
||||||
|
|
||||||
private ConsumerEventSource queueConsumerEventSource;
|
|
||||||
private Connection connection;
|
|
||||||
private Session session;
|
|
||||||
private ActiveMQTempTopic tempTopic;
|
|
||||||
private ActiveMQTempQueue tempQueue;
|
|
||||||
|
|
||||||
public void testDeleteTempTopicDeletesAvisoryTopics() throws Exception {
|
|
||||||
topicConsumerEventSource.start();
|
|
||||||
|
|
||||||
MessageConsumer consumer = createConsumer(tempTopic);
|
|
||||||
assertConsumerEvent(1, true);
|
|
||||||
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getConsumerAdvisoryTopic(tempTopic);
|
|
||||||
assertTrue(destinationExists(advisoryTopic));
|
|
||||||
|
|
||||||
consumer.close();
|
|
||||||
|
|
||||||
// Once we delete the topic, the advisory topic for the destination
|
|
||||||
// should also be deleted.
|
|
||||||
tempTopic.delete();
|
|
||||||
|
|
||||||
assertFalse(destinationExists(advisoryTopic));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDeleteTempQueueDeletesAvisoryTopics() throws Exception {
|
|
||||||
queueConsumerEventSource.start();
|
|
||||||
|
|
||||||
MessageConsumer consumer = createConsumer(tempQueue);
|
|
||||||
assertConsumerEvent(1, true);
|
|
||||||
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getConsumerAdvisoryTopic(tempQueue);
|
|
||||||
assertTrue(destinationExists(advisoryTopic));
|
|
||||||
|
|
||||||
consumer.close();
|
|
||||||
|
|
||||||
// Once we delete the queue, the advisory topic for the destination
|
|
||||||
// should also be deleted.
|
|
||||||
tempQueue.delete();
|
|
||||||
|
|
||||||
assertFalse(destinationExists(advisoryTopic));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean destinationExists(Destination dest) throws Exception {
|
|
||||||
RegionBroker rb = (RegionBroker) broker.getBroker().getAdaptor(RegionBroker.class);
|
|
||||||
return rb.getTopicRegion().getDestinationMap().containsKey(dest) || rb.getQueueRegion().getDestinationMap().containsKey(dest) || rb.getTempTopicRegion().getDestinationMap().containsKey(dest) || rb.getTempQueueRegion().getDestinationMap().containsKey(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConsumerEvent(ConsumerEvent event) {
|
|
||||||
eventQueue.add(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
connection = createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
|
|
||||||
tempTopic = (ActiveMQTempTopic) session.createTemporaryTopic();
|
|
||||||
topicConsumerEventSource = new ConsumerEventSource(connection, tempTopic);
|
|
||||||
topicConsumerEventSource.setConsumerListener(this);
|
|
||||||
|
|
||||||
tempQueue = (ActiveMQTempQueue) session.createTemporaryQueue();
|
|
||||||
queueConsumerEventSource = new ConsumerEventSource(connection, tempQueue);
|
|
||||||
queueConsumerEventSource.setConsumerListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
if (connection != null) {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void assertConsumerEvent(int count, boolean started) throws InterruptedException {
|
|
||||||
ConsumerEvent event = waitForConsumerEvent();
|
|
||||||
assertEquals("Consumer count", count, event.getConsumerCount());
|
|
||||||
assertEquals("started", started, event.isStarted());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MessageConsumer createConsumer(Destination dest) throws JMSException {
|
|
||||||
final String consumerText = "Consumer: " + (++consumerCounter);
|
|
||||||
LOG.info("Creating consumer: " + consumerText + " on destination: " + dest);
|
|
||||||
|
|
||||||
MessageConsumer consumer = session.createConsumer(dest);
|
|
||||||
consumer.setMessageListener(new MessageListener() {
|
|
||||||
@Override
|
|
||||||
public void onMessage(Message message) {
|
|
||||||
LOG.info("Received message by: " + consumerText + " message: " + message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return consumer;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ConsumerEvent waitForConsumerEvent() throws InterruptedException {
|
|
||||||
ConsumerEvent answer = eventQueue.poll(1000, TimeUnit.MILLISECONDS);
|
|
||||||
assertTrue("Should have received a consumer event!", answer != null);
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,112 +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.advisory;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TemporaryQueue;
|
|
||||||
import javax.jms.TemporaryTopic;
|
|
||||||
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
import org.apache.activemq.broker.region.Destination;
|
|
||||||
import org.apache.activemq.broker.region.RegionBroker;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class TempDestLoadTest extends EmbeddedBrokerTestSupport {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(TempDestLoadTest.class);
|
|
||||||
|
|
||||||
protected int consumerCounter;
|
|
||||||
private Connection connection;
|
|
||||||
private Session session;
|
|
||||||
private static final int MESSAGE_COUNT = 2000;
|
|
||||||
|
|
||||||
public void testLoadTempAdvisoryQueues() throws Exception {
|
|
||||||
|
|
||||||
for (int i = 0; i < MESSAGE_COUNT; i++) {
|
|
||||||
TemporaryQueue tempQueue = session.createTemporaryQueue();
|
|
||||||
MessageConsumer consumer = session.createConsumer(tempQueue);
|
|
||||||
MessageProducer producer = session.createProducer(tempQueue);
|
|
||||||
consumer.close();
|
|
||||||
producer.close();
|
|
||||||
tempQueue.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
AdvisoryBroker ab = (AdvisoryBroker) broker.getBroker().getAdaptor(AdvisoryBroker.class);
|
|
||||||
|
|
||||||
assertTrue(ab.getAdvisoryDestinations().size() == 0);
|
|
||||||
assertTrue(ab.getAdvisoryConsumers().size() == 0);
|
|
||||||
assertTrue(ab.getAdvisoryProducers().size() == 0);
|
|
||||||
|
|
||||||
RegionBroker rb = (RegionBroker) broker.getBroker().getAdaptor(RegionBroker.class);
|
|
||||||
|
|
||||||
for (Destination dest : rb.getDestinationMap().values()) {
|
|
||||||
LOG.debug("Destination: {}", dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
// there should be at least 2 destinations - advisories -
|
|
||||||
// 1 for the connection + 1 generic ones
|
|
||||||
assertTrue("Should be at least 2 destinations", rb.getDestinationMap().size() > 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testLoadTempAdvisoryTopics() throws Exception {
|
|
||||||
for (int i = 0; i < MESSAGE_COUNT; i++) {
|
|
||||||
TemporaryTopic tempTopic = session.createTemporaryTopic();
|
|
||||||
MessageConsumer consumer = session.createConsumer(tempTopic);
|
|
||||||
MessageProducer producer = session.createProducer(tempTopic);
|
|
||||||
consumer.close();
|
|
||||||
producer.close();
|
|
||||||
tempTopic.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
AdvisoryBroker ab = (AdvisoryBroker) broker.getBroker().getAdaptor(AdvisoryBroker.class);
|
|
||||||
assertTrue(ab.getAdvisoryDestinations().size() == 0);
|
|
||||||
assertTrue(ab.getAdvisoryConsumers().size() == 0);
|
|
||||||
assertTrue(ab.getAdvisoryProducers().size() == 0);
|
|
||||||
RegionBroker rb = (RegionBroker) broker.getBroker().getAdaptor(RegionBroker.class);
|
|
||||||
|
|
||||||
for (Destination dest : rb.getDestinationMap().values()) {
|
|
||||||
LOG.debug("Destination: {}", dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
// there should be at least 2 destinations - advisories -
|
|
||||||
// 1 for the connection + 1 generic ones
|
|
||||||
assertTrue("Should be at least 2 destinations", rb.getDestinationMap().size() > 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
connection = createConnection();
|
|
||||||
connection.start();
|
|
||||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
if (connection != null) {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,170 +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.advisory;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageListener;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TemporaryQueue;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
import org.apache.activemq.broker.region.RegionBroker;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
|
|
||||||
public class TempQueueMemoryTest extends EmbeddedBrokerTestSupport {
|
|
||||||
|
|
||||||
protected Connection serverConnection;
|
|
||||||
protected Session serverSession;
|
|
||||||
protected Connection clientConnection;
|
|
||||||
protected Session clientSession;
|
|
||||||
protected Destination serverDestination;
|
|
||||||
protected int messagesToSend = 10;
|
|
||||||
protected boolean deleteTempQueue = true;
|
|
||||||
protected boolean serverTransactional = false;
|
|
||||||
protected boolean clientTransactional = false;
|
|
||||||
protected int numConsumers = 1;
|
|
||||||
protected int numProducers = 1;
|
|
||||||
|
|
||||||
public void testConcurrentProducerRequestReply() throws Exception {
|
|
||||||
numProducers = 10;
|
|
||||||
testLoadRequestReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testLoadRequestReply() throws Exception {
|
|
||||||
for (int i = 0; i < numConsumers; i++) {
|
|
||||||
serverSession.createConsumer(serverDestination).setMessageListener(new MessageListener() {
|
|
||||||
@Override
|
|
||||||
public void onMessage(Message msg) {
|
|
||||||
try {
|
|
||||||
Destination replyTo = msg.getJMSReplyTo();
|
|
||||||
MessageProducer producer = serverSession.createProducer(replyTo);
|
|
||||||
producer.send(replyTo, msg);
|
|
||||||
if (serverTransactional) {
|
|
||||||
serverSession.commit();
|
|
||||||
}
|
|
||||||
producer.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class Producer extends Thread {
|
|
||||||
|
|
||||||
private final int numToSend;
|
|
||||||
|
|
||||||
public Producer(int numToSend) {
|
|
||||||
this.numToSend = numToSend;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
Session session = clientConnection.createSession(clientTransactional, clientTransactional ? Session.SESSION_TRANSACTED : Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageProducer producer = session.createProducer(serverDestination);
|
|
||||||
|
|
||||||
for (int i = 0; i < numToSend; i++) {
|
|
||||||
TemporaryQueue replyTo = session.createTemporaryQueue();
|
|
||||||
MessageConsumer consumer = session.createConsumer(replyTo);
|
|
||||||
Message msg = session.createMessage();
|
|
||||||
msg.setJMSReplyTo(replyTo);
|
|
||||||
producer.send(msg);
|
|
||||||
if (clientTransactional) {
|
|
||||||
session.commit();
|
|
||||||
}
|
|
||||||
consumer.receive();
|
|
||||||
if (clientTransactional) {
|
|
||||||
session.commit();
|
|
||||||
}
|
|
||||||
consumer.close();
|
|
||||||
if (deleteTempQueue) {
|
|
||||||
replyTo.delete();
|
|
||||||
} else {
|
|
||||||
// temp queue will be cleaned up on clientConnection.close
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (JMSException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vector<Thread> threads = new Vector<>(numProducers);
|
|
||||||
for (int i = 0; i < numProducers; i++) {
|
|
||||||
threads.add(new Producer(messagesToSend / numProducers));
|
|
||||||
}
|
|
||||||
startAndJoinThreads(threads);
|
|
||||||
|
|
||||||
clientSession.close();
|
|
||||||
serverSession.close();
|
|
||||||
clientConnection.close();
|
|
||||||
serverConnection.close();
|
|
||||||
|
|
||||||
AdvisoryBroker ab = (AdvisoryBroker) broker.getBroker().getAdaptor(AdvisoryBroker.class);
|
|
||||||
|
|
||||||
// The server destination will be left
|
|
||||||
assertTrue(ab.getAdvisoryDestinations().size() == 1);
|
|
||||||
|
|
||||||
assertTrue("should be zero but is " + ab.getAdvisoryConsumers().size(), ab.getAdvisoryConsumers().size() == 0);
|
|
||||||
assertTrue("should be zero but is " + ab.getAdvisoryProducers().size(), ab.getAdvisoryProducers().size() == 0);
|
|
||||||
|
|
||||||
RegionBroker rb = (RegionBroker) broker.getBroker().getAdaptor(RegionBroker.class);
|
|
||||||
|
|
||||||
assertTrue(rb.getDestinationMap().size() >= 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startAndJoinThreads(Vector<Thread> threads) throws Exception {
|
|
||||||
for (Thread thread : threads) {
|
|
||||||
thread.start();
|
|
||||||
}
|
|
||||||
for (Thread thread : threads) {
|
|
||||||
thread.join();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
serverConnection = createConnection();
|
|
||||||
serverConnection.start();
|
|
||||||
serverSession = serverConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
clientConnection = createConnection();
|
|
||||||
clientConnection.start();
|
|
||||||
clientSession = clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
serverDestination = createDestination();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
serverTransactional = clientTransactional = false;
|
|
||||||
numConsumers = numProducers = 1;
|
|
||||||
messagesToSend = 2000;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActiveMQDestination createDestination() {
|
|
||||||
return new ActiveMQQueue(getClass().getName());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,107 +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.blob;
|
|
||||||
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
import org.apache.activemq.command.ActiveMQBlobMessage;
|
|
||||||
|
|
||||||
public class FTPBlobDownloadStrategyTest extends FTPTestSupport {
|
|
||||||
|
|
||||||
final int FILE_SIZE = Short.MAX_VALUE * 10;
|
|
||||||
|
|
||||||
public void testDownload() throws Exception {
|
|
||||||
setConnection();
|
|
||||||
|
|
||||||
// create file
|
|
||||||
File uploadFile = new File(ftpHomeDirFile, "test.txt");
|
|
||||||
FileWriter wrt = new FileWriter(uploadFile);
|
|
||||||
|
|
||||||
wrt.write("hello world");
|
|
||||||
|
|
||||||
for (int ix = 0; ix < FILE_SIZE; ++ix) {
|
|
||||||
wrt.write("a");
|
|
||||||
}
|
|
||||||
|
|
||||||
wrt.close();
|
|
||||||
|
|
||||||
ActiveMQBlobMessage message = new ActiveMQBlobMessage();
|
|
||||||
BlobDownloadStrategy strategy = new FTPBlobDownloadStrategy(new BlobTransferPolicy());
|
|
||||||
InputStream stream;
|
|
||||||
try {
|
|
||||||
message.setURL(new URL(ftpUrl + "test.txt"));
|
|
||||||
stream = strategy.getInputStream(message);
|
|
||||||
int i = stream.read();
|
|
||||||
StringBuilder sb = new StringBuilder(2048);
|
|
||||||
while (i != -1) {
|
|
||||||
sb.append((char) i);
|
|
||||||
i = stream.read();
|
|
||||||
}
|
|
||||||
assertEquals("hello world", sb.toString().substring(0, "hello world".length()));
|
|
||||||
assertEquals(FILE_SIZE, sb.toString().substring("hello world".length()).length());
|
|
||||||
|
|
||||||
assertTrue(uploadFile.exists());
|
|
||||||
strategy.deleteFile(message);
|
|
||||||
assertFalse(uploadFile.exists());
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
assertTrue(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testWrongAuthentification() throws MalformedURLException {
|
|
||||||
ActiveMQBlobMessage message = new ActiveMQBlobMessage();
|
|
||||||
BlobDownloadStrategy strategy = new FTPBlobDownloadStrategy(new BlobTransferPolicy());
|
|
||||||
try {
|
|
||||||
message.setURL(new URL("ftp://" + userNamePass + "_wrong:" + userNamePass + "@localhost:" + ftpPort + "/ftptest/"));
|
|
||||||
strategy.getInputStream(message);
|
|
||||||
} catch (JMSException e) {
|
|
||||||
assertEquals("Wrong Exception", "Cant Authentificate to FTP-Server", e.getMessage());
|
|
||||||
return;
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println(e);
|
|
||||||
assertTrue("Wrong Exception " + e, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue("Expect Exception", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testWrongFTPPort() throws MalformedURLException {
|
|
||||||
ActiveMQBlobMessage message = new ActiveMQBlobMessage();
|
|
||||||
BlobDownloadStrategy strategy = new FTPBlobDownloadStrategy(new BlobTransferPolicy());
|
|
||||||
try {
|
|
||||||
message.setURL(new URL("ftp://" + userNamePass + ":" + userNamePass + "@localhost:" + 422 + "/ftptest/"));
|
|
||||||
strategy.getInputStream(message);
|
|
||||||
} catch (JMSException e) {
|
|
||||||
assertEquals("Wrong Exception", "Problem connecting the FTP-server", e.getMessage());
|
|
||||||
return;
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
assertTrue("Wrong Exception " + e, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue("Expect Exception", false);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,73 +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.blob;
|
|
||||||
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQSession;
|
|
||||||
import org.apache.activemq.BlobMessage;
|
|
||||||
import org.apache.activemq.command.ActiveMQBlobMessage;
|
|
||||||
|
|
||||||
public class FTPBlobTest extends FTPTestSupport {
|
|
||||||
|
|
||||||
public void testBlobFile() throws Exception {
|
|
||||||
setConnection();
|
|
||||||
// first create Message
|
|
||||||
File file = File.createTempFile("amq-data-file-", ".dat");
|
|
||||||
// lets write some data
|
|
||||||
String content = "hello world " + System.currentTimeMillis();
|
|
||||||
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
|
|
||||||
writer.append(content);
|
|
||||||
writer.close();
|
|
||||||
|
|
||||||
ActiveMQSession session = (ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageProducer producer = session.createProducer(destination);
|
|
||||||
MessageConsumer consumer = session.createConsumer(destination);
|
|
||||||
BlobMessage message = session.createBlobMessage(file);
|
|
||||||
message.setName("fileName");
|
|
||||||
|
|
||||||
producer.send(message);
|
|
||||||
Thread.sleep(1000);
|
|
||||||
|
|
||||||
// check message send
|
|
||||||
Message msg = consumer.receive(1000);
|
|
||||||
assertTrue(msg instanceof ActiveMQBlobMessage);
|
|
||||||
|
|
||||||
assertEquals("name is correct", "fileName", ((ActiveMQBlobMessage) msg).getName());
|
|
||||||
InputStream input = ((ActiveMQBlobMessage) msg).getInputStream();
|
|
||||||
StringBuilder b = new StringBuilder();
|
|
||||||
int i = input.read();
|
|
||||||
while (i != -1) {
|
|
||||||
b.append((char) i);
|
|
||||||
i = input.read();
|
|
||||||
}
|
|
||||||
input.close();
|
|
||||||
File uploaded = new File(ftpHomeDirFile, msg.getJMSMessageID().toString().replace(":", "_"));
|
|
||||||
assertEquals(content, b.toString());
|
|
||||||
assertTrue(uploaded.exists());
|
|
||||||
((ActiveMQBlobMessage) msg).deleteFile();
|
|
||||||
assertFalse(uploaded.exists());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,73 +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.blob;
|
|
||||||
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.ActiveMQSession;
|
|
||||||
import org.apache.activemq.command.ActiveMQBlobMessage;
|
|
||||||
|
|
||||||
public class FTPBlobUploadStrategyTest extends FTPTestSupport {
|
|
||||||
|
|
||||||
public void testFileUpload() throws Exception {
|
|
||||||
setConnection();
|
|
||||||
File file = File.createTempFile("amq-data-file-", ".dat");
|
|
||||||
// lets write some data
|
|
||||||
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
|
|
||||||
writer.append("hello world");
|
|
||||||
writer.close();
|
|
||||||
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
((ActiveMQConnection) connection).setCopyMessageOnSend(false);
|
|
||||||
|
|
||||||
ActiveMQBlobMessage message = (ActiveMQBlobMessage) ((ActiveMQSession) session).createBlobMessage(file);
|
|
||||||
message.setJMSMessageID("testmessage");
|
|
||||||
message.onSend();
|
|
||||||
assertEquals(ftpUrl + "ID_testmessage", message.getURL().toString());
|
|
||||||
File uploaded = new File(ftpHomeDirFile, "ID_testmessage");
|
|
||||||
assertTrue("File doesn't exists", uploaded.exists());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testWriteDenied() throws Exception {
|
|
||||||
userNamePass = "guest";
|
|
||||||
setConnection();
|
|
||||||
File file = File.createTempFile("amq-data-file-", ".dat");
|
|
||||||
// lets write some data
|
|
||||||
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
|
|
||||||
writer.append("hello world");
|
|
||||||
writer.close();
|
|
||||||
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
((ActiveMQConnection) connection).setCopyMessageOnSend(false);
|
|
||||||
|
|
||||||
ActiveMQBlobMessage message = (ActiveMQBlobMessage) ((ActiveMQSession) session).createBlobMessage(file);
|
|
||||||
message.setJMSMessageID("testmessage");
|
|
||||||
try {
|
|
||||||
message.onSend();
|
|
||||||
} catch (JMSException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fail("Should have failed with permission denied exception!");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,115 +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.blob;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
import org.apache.activemq.util.IOHelper;
|
|
||||||
import org.apache.ftpserver.FtpServer;
|
|
||||||
import org.apache.ftpserver.FtpServerFactory;
|
|
||||||
import org.apache.ftpserver.ftplet.Authority;
|
|
||||||
import org.apache.ftpserver.ftplet.UserManager;
|
|
||||||
import org.apache.ftpserver.listener.ListenerFactory;
|
|
||||||
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
|
|
||||||
import org.apache.ftpserver.usermanager.impl.BaseUser;
|
|
||||||
import org.apache.ftpserver.usermanager.impl.WritePermission;
|
|
||||||
import org.jmock.Mockery;
|
|
||||||
|
|
||||||
public abstract class FTPTestSupport extends EmbeddedBrokerTestSupport {
|
|
||||||
|
|
||||||
protected static final String ftpServerListenerName = "default";
|
|
||||||
protected Connection connection;
|
|
||||||
protected FtpServer server;
|
|
||||||
String userNamePass = "activemq";
|
|
||||||
|
|
||||||
Mockery context = null;
|
|
||||||
String ftpUrl;
|
|
||||||
int ftpPort;
|
|
||||||
|
|
||||||
final File ftpHomeDirFile = new File("target/FTPBlobTest/ftptest");
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
|
|
||||||
if (ftpHomeDirFile.getParentFile().exists()) {
|
|
||||||
IOHelper.deleteFile(ftpHomeDirFile.getParentFile());
|
|
||||||
}
|
|
||||||
ftpHomeDirFile.mkdirs();
|
|
||||||
ftpHomeDirFile.getParentFile().deleteOnExit();
|
|
||||||
|
|
||||||
FtpServerFactory serverFactory = new FtpServerFactory();
|
|
||||||
ListenerFactory factory = new ListenerFactory();
|
|
||||||
|
|
||||||
PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
|
|
||||||
UserManager userManager = userManagerFactory.createUserManager();
|
|
||||||
|
|
||||||
BaseUser user = new BaseUser();
|
|
||||||
user.setName("activemq");
|
|
||||||
user.setPassword("activemq");
|
|
||||||
user.setHomeDirectory(ftpHomeDirFile.getParent());
|
|
||||||
|
|
||||||
// authorize user
|
|
||||||
List<Authority> auths = new ArrayList<>();
|
|
||||||
Authority auth = new WritePermission();
|
|
||||||
auths.add(auth);
|
|
||||||
user.setAuthorities(auths);
|
|
||||||
|
|
||||||
userManager.save(user);
|
|
||||||
|
|
||||||
BaseUser guest = new BaseUser();
|
|
||||||
guest.setName("guest");
|
|
||||||
guest.setPassword("guest");
|
|
||||||
guest.setHomeDirectory(ftpHomeDirFile.getParent());
|
|
||||||
|
|
||||||
userManager.save(guest);
|
|
||||||
|
|
||||||
serverFactory.setUserManager(userManager);
|
|
||||||
factory.setPort(0);
|
|
||||||
serverFactory.addListener(ftpServerListenerName, factory.createListener());
|
|
||||||
server = serverFactory.createServer();
|
|
||||||
server.start();
|
|
||||||
ftpPort = serverFactory.getListener(ftpServerListenerName).getPort();
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setConnection() throws Exception {
|
|
||||||
ftpUrl = "ftp://" + userNamePass + ":" + userNamePass + "@localhost:" + ftpPort + "/ftptest/";
|
|
||||||
bindAddress = "vm://localhost?jms.blobTransferPolicy.defaultUploadUrl=" + ftpUrl;
|
|
||||||
|
|
||||||
connectionFactory = createConnectionFactory();
|
|
||||||
|
|
||||||
connection = createConnection();
|
|
||||||
connection.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
if (connection != null) {
|
|
||||||
connection.stop();
|
|
||||||
}
|
|
||||||
super.tearDown();
|
|
||||||
if (server != null) {
|
|
||||||
server.stop();
|
|
||||||
}
|
|
||||||
IOHelper.deleteFile(ftpHomeDirFile.getParentFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,103 +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.blob;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQSession;
|
|
||||||
import org.apache.activemq.BlobMessage;
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
import org.apache.activemq.command.ActiveMQBlobMessage;
|
|
||||||
import org.apache.activemq.util.IOHelper;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class FilesystemBlobTest extends EmbeddedBrokerTestSupport {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(FilesystemBlobTest.class);
|
|
||||||
|
|
||||||
private Connection connection;
|
|
||||||
private final String tmpDir = System.getProperty("user.dir") + "/target/FilesystemBlobTest";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
// replace \ with / to let it work on windows too
|
|
||||||
String fileUrl = "file:///" + tmpDir.replaceAll("\\\\", "/");
|
|
||||||
LOG.info("Using file: " + fileUrl);
|
|
||||||
bindAddress = "vm://localhost?jms.blobTransferPolicy.defaultUploadUrl=" + fileUrl;
|
|
||||||
|
|
||||||
connectionFactory = createConnectionFactory();
|
|
||||||
|
|
||||||
connection = createConnection();
|
|
||||||
connection.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testBlobFile() throws Exception {
|
|
||||||
// first create Message
|
|
||||||
File file = File.createTempFile("amq-data-file-", ".dat");
|
|
||||||
// lets write some data
|
|
||||||
String content = "hello world " + System.currentTimeMillis();
|
|
||||||
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
|
|
||||||
writer.append(content);
|
|
||||||
writer.close();
|
|
||||||
|
|
||||||
ActiveMQSession session = (ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageProducer producer = session.createProducer(destination);
|
|
||||||
MessageConsumer consumer = session.createConsumer(destination);
|
|
||||||
BlobMessage message = session.createBlobMessage(file);
|
|
||||||
|
|
||||||
producer.send(message);
|
|
||||||
Thread.sleep(1000);
|
|
||||||
|
|
||||||
// check message send
|
|
||||||
Message msg = consumer.receive(1000);
|
|
||||||
assertTrue(msg instanceof ActiveMQBlobMessage);
|
|
||||||
|
|
||||||
InputStream input = ((ActiveMQBlobMessage) msg).getInputStream();
|
|
||||||
StringBuilder b = new StringBuilder();
|
|
||||||
int i = input.read();
|
|
||||||
while (i != -1) {
|
|
||||||
b.append((char) i);
|
|
||||||
i = input.read();
|
|
||||||
}
|
|
||||||
input.close();
|
|
||||||
File uploaded = new File(tmpDir, msg.getJMSMessageID().toString().replace(":", "_"));
|
|
||||||
assertEquals(content, b.toString());
|
|
||||||
assertTrue(uploaded.exists());
|
|
||||||
((ActiveMQBlobMessage) msg).deleteFile();
|
|
||||||
assertFalse(uploaded.exists());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
if (connection != null) {
|
|
||||||
connection.stop();
|
|
||||||
}
|
|
||||||
super.tearDown();
|
|
||||||
|
|
||||||
IOHelper.deleteFile(new File(tmpDir));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,184 +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.broker;
|
|
||||||
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.RedeliveryPolicy;
|
|
||||||
import org.apache.activemq.broker.region.policy.RedeliveryPolicyMap;
|
|
||||||
import org.apache.activemq.broker.region.policy.SharedDeadLetterStrategy;
|
|
||||||
import org.apache.activemq.broker.util.RedeliveryPlugin;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class BrokerRedeliveryTest extends org.apache.activemq.TestSupport {
|
|
||||||
|
|
||||||
static final Logger LOG = LoggerFactory.getLogger(BrokerRedeliveryTest.class);
|
|
||||||
BrokerService broker = null;
|
|
||||||
|
|
||||||
final ActiveMQQueue destination = new ActiveMQQueue("Redelivery");
|
|
||||||
final String data = "hi";
|
|
||||||
final long redeliveryDelayMillis = 2000;
|
|
||||||
long initialRedeliveryDelayMillis = 4000;
|
|
||||||
int maxBrokerRedeliveries = 2;
|
|
||||||
|
|
||||||
public void testScheduledRedelivery() throws Exception {
|
|
||||||
doTestScheduledRedelivery(maxBrokerRedeliveries, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testInfiniteRedelivery() throws Exception {
|
|
||||||
initialRedeliveryDelayMillis = redeliveryDelayMillis;
|
|
||||||
maxBrokerRedeliveries = RedeliveryPolicy.NO_MAXIMUM_REDELIVERIES;
|
|
||||||
doTestScheduledRedelivery(RedeliveryPolicy.DEFAULT_MAXIMUM_REDELIVERIES + 1, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doTestScheduledRedelivery(int maxBrokerRedeliveriesToValidate, boolean validateDLQ) throws Exception {
|
|
||||||
|
|
||||||
startBroker(true);
|
|
||||||
sendMessage(0);
|
|
||||||
|
|
||||||
ActiveMQConnection consumerConnection = (ActiveMQConnection) createConnection();
|
|
||||||
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
|
|
||||||
redeliveryPolicy.setInitialRedeliveryDelay(0);
|
|
||||||
redeliveryPolicy.setMaximumRedeliveries(0);
|
|
||||||
consumerConnection.setRedeliveryPolicy(redeliveryPolicy);
|
|
||||||
consumerConnection.start();
|
|
||||||
Session consumerSession = consumerConnection.createSession(true, Session.SESSION_TRANSACTED);
|
|
||||||
MessageConsumer consumer = consumerSession.createConsumer(destination);
|
|
||||||
Message message = consumer.receive(1000);
|
|
||||||
assertNotNull("got message", message);
|
|
||||||
LOG.info("got: " + message);
|
|
||||||
consumerSession.rollback();
|
|
||||||
|
|
||||||
for (int i = 0; i < maxBrokerRedeliveriesToValidate; i++) {
|
|
||||||
Message shouldBeNull = consumer.receive(500);
|
|
||||||
assertNull("did not get message after redelivery count exceeded: " + shouldBeNull, shouldBeNull);
|
|
||||||
|
|
||||||
TimeUnit.SECONDS.sleep(3);
|
|
||||||
|
|
||||||
Message brokerRedeliveryMessage = consumer.receive(500);
|
|
||||||
LOG.info("got: " + brokerRedeliveryMessage);
|
|
||||||
assertNotNull("got message via broker redelivery after delay", brokerRedeliveryMessage);
|
|
||||||
assertEquals("message matches", message.getStringProperty("data"), brokerRedeliveryMessage.getStringProperty("data"));
|
|
||||||
assertEquals("has expiryDelay specified", i == 0 ? initialRedeliveryDelayMillis : redeliveryDelayMillis, brokerRedeliveryMessage.getLongProperty(RedeliveryPlugin.REDELIVERY_DELAY));
|
|
||||||
|
|
||||||
consumerSession.rollback();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (validateDLQ) {
|
|
||||||
MessageConsumer dlqConsumer = consumerSession.createConsumer(new ActiveMQQueue(SharedDeadLetterStrategy.DEFAULT_DEAD_LETTER_QUEUE_NAME));
|
|
||||||
Message dlqMessage = dlqConsumer.receive(2000);
|
|
||||||
assertNotNull("Got message from dql", dlqMessage);
|
|
||||||
assertEquals("message matches", message.getStringProperty("data"), dlqMessage.getStringProperty("data"));
|
|
||||||
consumerSession.commit();
|
|
||||||
} else {
|
|
||||||
// consume/commit ok
|
|
||||||
message = consumer.receive(3000);
|
|
||||||
assertNotNull("got message", message);
|
|
||||||
assertEquals("redeliveries accounted for", maxBrokerRedeliveriesToValidate + 2, message.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
consumerSession.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
consumerConnection.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testNoScheduledRedeliveryOfExpired() throws Exception {
|
|
||||||
startBroker(true);
|
|
||||||
ActiveMQConnection consumerConnection = (ActiveMQConnection) createConnection();
|
|
||||||
consumerConnection.start();
|
|
||||||
Session consumerSession = consumerConnection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
MessageConsumer consumer = consumerSession.createConsumer(destination);
|
|
||||||
sendMessage(1500);
|
|
||||||
Message message = consumer.receive(1000);
|
|
||||||
assertNotNull("got message", message);
|
|
||||||
|
|
||||||
// ensure there is another consumer to redispatch to
|
|
||||||
MessageConsumer redeliverConsumer = consumerSession.createConsumer(destination);
|
|
||||||
|
|
||||||
// allow consumed to expire so it gets redelivered
|
|
||||||
TimeUnit.SECONDS.sleep(2);
|
|
||||||
consumer.close();
|
|
||||||
|
|
||||||
// should go to dlq as it has expired
|
|
||||||
// validate DLQ
|
|
||||||
MessageConsumer dlqConsumer = consumerSession.createConsumer(new ActiveMQQueue(SharedDeadLetterStrategy.DEFAULT_DEAD_LETTER_QUEUE_NAME));
|
|
||||||
Message dlqMessage = dlqConsumer.receive(2000);
|
|
||||||
assertNotNull("Got message from dql", dlqMessage);
|
|
||||||
assertEquals("message matches", message.getStringProperty("data"), dlqMessage.getStringProperty("data"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendMessage(int timeToLive) throws Exception {
|
|
||||||
ActiveMQConnection producerConnection = (ActiveMQConnection) createConnection();
|
|
||||||
producerConnection.start();
|
|
||||||
Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageProducer producer = producerSession.createProducer(destination);
|
|
||||||
if (timeToLive > 0) {
|
|
||||||
producer.setTimeToLive(timeToLive);
|
|
||||||
}
|
|
||||||
Message message = producerSession.createMessage();
|
|
||||||
message.setStringProperty("data", data);
|
|
||||||
producer.send(message);
|
|
||||||
producerConnection.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startBroker(boolean deleteMessages) throws Exception {
|
|
||||||
broker = new BrokerService();
|
|
||||||
broker.setSchedulerSupport(true);
|
|
||||||
|
|
||||||
RedeliveryPlugin redeliveryPlugin = new RedeliveryPlugin();
|
|
||||||
|
|
||||||
RedeliveryPolicy brokerRedeliveryPolicy = new RedeliveryPolicy();
|
|
||||||
brokerRedeliveryPolicy.setRedeliveryDelay(redeliveryDelayMillis);
|
|
||||||
brokerRedeliveryPolicy.setInitialRedeliveryDelay(initialRedeliveryDelayMillis);
|
|
||||||
brokerRedeliveryPolicy.setMaximumRedeliveries(maxBrokerRedeliveries);
|
|
||||||
|
|
||||||
RedeliveryPolicyMap redeliveryPolicyMap = new RedeliveryPolicyMap();
|
|
||||||
redeliveryPolicyMap.setDefaultEntry(brokerRedeliveryPolicy);
|
|
||||||
redeliveryPlugin.setRedeliveryPolicyMap(redeliveryPolicyMap);
|
|
||||||
|
|
||||||
broker.setPlugins(new BrokerPlugin[]{redeliveryPlugin});
|
|
||||||
|
|
||||||
if (deleteMessages) {
|
|
||||||
broker.setDeleteAllMessagesOnStartup(true);
|
|
||||||
}
|
|
||||||
broker.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopBroker() throws Exception {
|
|
||||||
if (broker != null)
|
|
||||||
broker.stop();
|
|
||||||
broker = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
return new ActiveMQConnectionFactory("vm://localhost");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
stopBroker();
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,84 +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.broker;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.activemq.network.NetworkConnector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for the BrokerService class
|
|
||||||
*
|
|
||||||
* @author chirino
|
|
||||||
*/
|
|
||||||
public class BrokerServiceTest extends TestCase {
|
|
||||||
|
|
||||||
public void testAddRemoveTransportsWithJMX() throws Exception {
|
|
||||||
BrokerService service = new BrokerService();
|
|
||||||
service.setUseJmx(true);
|
|
||||||
service.setPersistent(false);
|
|
||||||
TransportConnector connector = service.addConnector("tcp://localhost:0");
|
|
||||||
service.start();
|
|
||||||
|
|
||||||
service.removeConnector(connector);
|
|
||||||
connector.stop();
|
|
||||||
service.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAddRemoveTransportsWithoutJMX() throws Exception {
|
|
||||||
BrokerService service = new BrokerService();
|
|
||||||
service.setPersistent(false);
|
|
||||||
service.setUseJmx(false);
|
|
||||||
TransportConnector connector = service.addConnector("tcp://localhost:0");
|
|
||||||
service.start();
|
|
||||||
|
|
||||||
service.removeConnector(connector);
|
|
||||||
connector.stop();
|
|
||||||
service.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAddRemoveNetworkWithJMX() throws Exception {
|
|
||||||
BrokerService service = new BrokerService();
|
|
||||||
service.setPersistent(false);
|
|
||||||
service.setUseJmx(true);
|
|
||||||
NetworkConnector connector = service.addNetworkConnector("multicast://default?group=group-" + System.currentTimeMillis());
|
|
||||||
service.start();
|
|
||||||
|
|
||||||
service.removeNetworkConnector(connector);
|
|
||||||
connector.stop();
|
|
||||||
service.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAddRemoveNetworkWithoutJMX() throws Exception {
|
|
||||||
BrokerService service = new BrokerService();
|
|
||||||
service.setPersistent(false);
|
|
||||||
service.setUseJmx(false);
|
|
||||||
NetworkConnector connector = service.addNetworkConnector("multicast://default?group=group-" + System.currentTimeMillis());
|
|
||||||
service.start();
|
|
||||||
|
|
||||||
service.removeNetworkConnector(connector);
|
|
||||||
connector.stop();
|
|
||||||
service.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSystemUsage() {
|
|
||||||
BrokerService service = new BrokerService();
|
|
||||||
assertEquals(1024 * 1024 * 1024, service.getSystemUsage().getMemoryUsage().getLimit());
|
|
||||||
assertEquals(1024L * 1024 * 1024 * 50, service.getSystemUsage().getTempUsage().getLimit());
|
|
||||||
assertEquals(1024L * 1024 * 1024 * 100, service.getSystemUsage().getStoreUsage().getLimit());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +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.broker;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
import org.apache.activemq.advisory.AdvisorySupport;
|
|
||||||
import org.apache.activemq.command.ConnectionInfo;
|
|
||||||
import org.apache.activemq.command.ConsumerId;
|
|
||||||
import org.apache.activemq.command.ConsumerInfo;
|
|
||||||
import org.apache.activemq.command.SessionId;
|
|
||||||
|
|
||||||
public class ConcurrentConnectSimulationTest extends BrokerTestSupport {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* simulate failover and retry of connection before broker has killed connection
|
|
||||||
* which appears as a concurrent connect request to the broker
|
|
||||||
* see: https://issues.apache.org/activemq/browse/AMQ-2241
|
|
||||||
*/
|
|
||||||
public void testConcurrentConnection() throws Exception {
|
|
||||||
|
|
||||||
StubConnection connection1 = createConnection();
|
|
||||||
StubConnection connection2 = createConnection();
|
|
||||||
|
|
||||||
// reuse same connection info
|
|
||||||
ConnectionInfo connectionInfo = createConnectionInfo();
|
|
||||||
connection1.request(connectionInfo);
|
|
||||||
connection2.request(connectionInfo);
|
|
||||||
|
|
||||||
// second one should win out, verify using consumer on default session (watchAdvisories)
|
|
||||||
ConsumerId consumerId = new ConsumerId(new SessionId(connectionInfo.getConnectionId(), -1), 1);
|
|
||||||
ConsumerInfo consumerInfo = new ConsumerInfo(consumerId);
|
|
||||||
consumerInfo.setDestination(AdvisorySupport.TEMP_DESTINATION_COMPOSITE_ADVISORY_TOPIC);
|
|
||||||
|
|
||||||
connection2.request(consumerInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(ConcurrentConnectSimulationTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(suite());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +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.broker;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
import org.apache.activemq.broker.region.Destination;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
|
||||||
import org.apache.activemq.xbean.XBeanBrokerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class CreateDestinationsOnStartupViaXBeanTest extends EmbeddedBrokerTestSupport {
|
|
||||||
|
|
||||||
public void testNewDestinationsAreCreatedOnStartup() throws Exception {
|
|
||||||
assertQueueCreated("FOO.BAR", true);
|
|
||||||
assertQueueCreated("FOO.DoesNotExist", false);
|
|
||||||
|
|
||||||
assertTopicCreated("SOME.TOPIC", true);
|
|
||||||
assertTopicCreated("FOO.DoesNotExist", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void assertQueueCreated(String name, boolean expected) throws Exception {
|
|
||||||
assertDestinationCreated(new ActiveMQQueue(name), expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void assertTopicCreated(String name, boolean expected) throws Exception {
|
|
||||||
assertDestinationCreated(new ActiveMQTopic(name), expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void assertDestinationCreated(ActiveMQDestination destination, boolean expected) throws Exception {
|
|
||||||
Set<Destination> answer = broker.getBroker().getDestinations(destination);
|
|
||||||
int size = expected ? 1 : 0;
|
|
||||||
assertEquals("Could not find destination: " + destination + ". Size of found destinations: " + answer, size, answer.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
XBeanBrokerFactory factory = new XBeanBrokerFactory();
|
|
||||||
BrokerService answer = factory.createBroker(new URI(getBrokerConfigUri()));
|
|
||||||
|
|
||||||
// lets disable persistence as we are a test
|
|
||||||
answer.setPersistent(false);
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getBrokerConfigUri() {
|
|
||||||
return "org/apache/activemq/broker/destinations-on-start.xml";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +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.broker;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
public class DedicatedTaskRunnerBrokerTest extends BrokerTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
broker.setDedicatedTaskRunner(true);
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(DedicatedTaskRunnerBrokerTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(suite());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,120 +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.broker;
|
|
||||||
|
|
||||||
import javax.jms.DeliveryMode;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ConnectionInfo;
|
|
||||||
import org.apache.activemq.command.ConsumerInfo;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.command.MessageAck;
|
|
||||||
import org.apache.activemq.command.ProducerInfo;
|
|
||||||
import org.apache.activemq.command.SessionInfo;
|
|
||||||
import org.apache.activemq.network.NetworkTestSupport;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pretend to be an abusive client that sends multiple identical ConsumerInfo
|
|
||||||
* commands and make sure the broker doesn't stall because of it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class DoubleSubscriptionTest extends NetworkTestSupport {
|
|
||||||
|
|
||||||
public ActiveMQDestination destination;
|
|
||||||
public int deliveryMode;
|
|
||||||
|
|
||||||
private String remoteURI = "tcp://localhost:0?wireFormat.tcpNoDelayEnabled=true";
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(DoubleSubscriptionTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(suite());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initCombosForTestDoubleSubscription() {
|
|
||||||
addCombinationValues("destination", new Object[]{new ActiveMQQueue("TEST"), new ActiveMQQueue("TEST")});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDoubleSubscription() throws Exception {
|
|
||||||
|
|
||||||
// Start a normal consumer on the remote broker
|
|
||||||
StubConnection connection1 = createRemoteConnection();
|
|
||||||
ConnectionInfo connectionInfo1 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo1 = createSessionInfo(connectionInfo1);
|
|
||||||
ConsumerInfo consumerInfo1 = createConsumerInfo(sessionInfo1, destination);
|
|
||||||
connection1.send(connectionInfo1);
|
|
||||||
connection1.send(sessionInfo1);
|
|
||||||
connection1.request(consumerInfo1);
|
|
||||||
|
|
||||||
// Start a normal producer on a remote broker
|
|
||||||
StubConnection connection2 = createRemoteConnection();
|
|
||||||
ConnectionInfo connectionInfo2 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo2 = createSessionInfo(connectionInfo2);
|
|
||||||
ProducerInfo producerInfo2 = createProducerInfo(sessionInfo2);
|
|
||||||
connection2.send(connectionInfo2);
|
|
||||||
connection2.send(sessionInfo2);
|
|
||||||
connection2.request(producerInfo2);
|
|
||||||
|
|
||||||
// Send a message to make sure the basics are working
|
|
||||||
connection2.request(createMessage(producerInfo2, destination, DeliveryMode.PERSISTENT));
|
|
||||||
|
|
||||||
Message m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNoMessagesLeft(connection1);
|
|
||||||
|
|
||||||
connection1.send(createAck(consumerInfo1, m1, 1, MessageAck.STANDARD_ACK_TYPE));
|
|
||||||
|
|
||||||
// Send a message to sit on the broker while we mess with it
|
|
||||||
connection2.request(createMessage(producerInfo2, destination, DeliveryMode.PERSISTENT));
|
|
||||||
|
|
||||||
// Now we're going to resend the same consumer commands again and see if
|
|
||||||
// the broker
|
|
||||||
// can handle it.
|
|
||||||
connection1.send(connectionInfo1);
|
|
||||||
connection1.send(sessionInfo1);
|
|
||||||
connection1.request(consumerInfo1);
|
|
||||||
|
|
||||||
// After this there should be 2 messages on the broker...
|
|
||||||
connection2.request(createMessage(producerInfo2, destination, DeliveryMode.PERSISTENT));
|
|
||||||
|
|
||||||
// ... let's start a fresh consumer...
|
|
||||||
connection1.stop();
|
|
||||||
StubConnection connection3 = createRemoteConnection();
|
|
||||||
ConnectionInfo connectionInfo3 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo3 = createSessionInfo(connectionInfo3);
|
|
||||||
ConsumerInfo consumerInfo3 = createConsumerInfo(sessionInfo3, destination);
|
|
||||||
connection3.send(connectionInfo3);
|
|
||||||
connection3.send(sessionInfo3);
|
|
||||||
connection3.request(consumerInfo3);
|
|
||||||
|
|
||||||
// ... and then grab the 2 that should be there.
|
|
||||||
assertNotNull(receiveMessage(connection3));
|
|
||||||
assertNotNull(receiveMessage(connection3));
|
|
||||||
assertNoMessagesLeft(connection3);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getRemoteURI() {
|
|
||||||
return remoteURI;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,90 +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.broker;
|
|
||||||
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TextMessage;
|
|
||||||
import javax.jms.Topic;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
|
||||||
import org.apache.activemq.transport.failover.FailoverTransport;
|
|
||||||
|
|
||||||
public class DurablePersistentFalseRestartTest extends BrokerRestartTestSupport {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureBroker(BrokerService broker) throws Exception {
|
|
||||||
super.configureBroker(broker);
|
|
||||||
broker.setPersistent(false);
|
|
||||||
broker.setPersistenceAdapter(new KahaDBPersistenceAdapter());
|
|
||||||
broker.addConnector("tcp://0.0.0.0:0");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testValidateNoPersistenceForDurableAfterRestart() throws Exception {
|
|
||||||
|
|
||||||
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("failover:(" + broker.getTransportConnectors().get(0).getPublishableConnectString() + ")");
|
|
||||||
ActiveMQConnection connection = (ActiveMQConnection) connectionFactory.createConnection();
|
|
||||||
connection.setClientID("clientId");
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
|
|
||||||
Topic destination = session.createTopic(queueName);
|
|
||||||
MessageConsumer consumer = session.createDurableSubscriber(destination, "subscriberName");
|
|
||||||
|
|
||||||
populateDestination(10, destination, connection);
|
|
||||||
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// make failover aware of the restarted auto assigned port
|
|
||||||
connection.getTransport().narrow(FailoverTransport.class).add(true, broker.getTransportConnectors().get(0).getPublishableConnectString());
|
|
||||||
|
|
||||||
TextMessage msg = (TextMessage) consumer.receive(4000);
|
|
||||||
assertNull("did not get a message when persistent=false, message: " + msg, msg);
|
|
||||||
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void populateDestination(final int nbMessages,
|
|
||||||
final Destination destination,
|
|
||||||
javax.jms.Connection connection) throws JMSException {
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageProducer producer = session.createProducer(destination);
|
|
||||||
for (int i = 1; i <= nbMessages; i++) {
|
|
||||||
producer.send(session.createTextMessage("<hello id='" + i + "'/>"));
|
|
||||||
}
|
|
||||||
producer.close();
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(DurablePersistentFalseRestartTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(suite());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,90 +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.broker;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
|
||||||
import org.apache.derby.jdbc.EmbeddedDataSource;
|
|
||||||
import org.apache.derby.jdbc.EmbeddedXADataSource;
|
|
||||||
|
|
||||||
public class JdbcXARecoveryBrokerTest extends XARecoveryBrokerTest {
|
|
||||||
|
|
||||||
EmbeddedXADataSource dataSource;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
dataSource = new EmbeddedXADataSource();
|
|
||||||
dataSource.setDatabaseName("derbyDb");
|
|
||||||
dataSource.setCreateDatabase("create");
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
stopDerby();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureBroker(BrokerService broker) throws Exception {
|
|
||||||
super.configureBroker(broker);
|
|
||||||
|
|
||||||
JDBCPersistenceAdapter jdbc = new JDBCPersistenceAdapter();
|
|
||||||
jdbc.setDataSource(dataSource);
|
|
||||||
broker.setPersistenceAdapter(jdbc);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void restartBroker() throws Exception {
|
|
||||||
broker.stop();
|
|
||||||
stopDerby();
|
|
||||||
dataSource = new EmbeddedXADataSource();
|
|
||||||
dataSource.setDatabaseName("derbyDb");
|
|
||||||
dataSource.setCreateDatabase("create");
|
|
||||||
|
|
||||||
broker = createRestartedBroker();
|
|
||||||
broker.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopDerby() {
|
|
||||||
LOG.info("STOPPING DB!@!!!!");
|
|
||||||
final EmbeddedDataSource ds = dataSource;
|
|
||||||
try {
|
|
||||||
ds.setShutdownDatabase("shutdown");
|
|
||||||
ds.getConnection();
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(JdbcXARecoveryBrokerTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(suite());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActiveMQDestination createDestination() {
|
|
||||||
return new ActiveMQQueue("test,special");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,85 +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.broker;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Session;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.broker.jmx.ManagementContext;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.demo.DefaultQueueSender;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A helper class which can be handy for running a broker in your IDE from the
|
|
||||||
* activemq-core module.
|
|
||||||
*/
|
|
||||||
public final class Main {
|
|
||||||
|
|
||||||
protected static boolean createConsumers;
|
|
||||||
|
|
||||||
private Main() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param args
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) {
|
|
||||||
try {
|
|
||||||
BrokerService broker = new BrokerService();
|
|
||||||
broker.setPersistent(false);
|
|
||||||
|
|
||||||
// String brokerDir = "xbean:...;
|
|
||||||
// System.setProperty("activemq.base", brokerDir);
|
|
||||||
// BrokerService broker = BrokerFactory.createBroker(new URI(brokerDir + "/activemq.xml"));
|
|
||||||
|
|
||||||
// for running on Java 5 without mx4j
|
|
||||||
ManagementContext managementContext = broker.getManagementContext();
|
|
||||||
managementContext.setFindTigerMbeanServer(true);
|
|
||||||
managementContext.setUseMBeanServer(true);
|
|
||||||
managementContext.setCreateConnector(false);
|
|
||||||
|
|
||||||
broker.setUseJmx(true);
|
|
||||||
// broker.setPlugins(new BrokerPlugin[] { new
|
|
||||||
// ConnectionDotFilePlugin(), new UDPTraceBrokerPlugin() });
|
|
||||||
broker.addConnector("tcp://localhost:61616");
|
|
||||||
broker.addConnector("stomp://localhost:61613");
|
|
||||||
broker.start();
|
|
||||||
|
|
||||||
// lets publish some messages so that there is some stuff to browse
|
|
||||||
DefaultQueueSender.main(new String[]{"Prices.Equity.IBM"});
|
|
||||||
DefaultQueueSender.main(new String[]{"Prices.Equity.MSFT"});
|
|
||||||
|
|
||||||
// lets create a dummy couple of consumers
|
|
||||||
if (createConsumers) {
|
|
||||||
Connection connection = new ActiveMQConnectionFactory().createConnection();
|
|
||||||
connection.start();
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
session.createConsumer(new ActiveMQQueue("Orders.IBM"));
|
|
||||||
session.createConsumer(new ActiveMQQueue("Orders.MSFT"), "price > 100");
|
|
||||||
Session session2 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
session2.createConsumer(new ActiveMQQueue("Orders.MSFT"), "price > 200");
|
|
||||||
} else {
|
|
||||||
// Lets wait for the broker
|
|
||||||
broker.waitUntilStopped();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("Failed: " + e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +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.broker;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
import org.apache.activemq.command.Command;
|
|
||||||
import org.apache.activemq.command.Response;
|
|
||||||
import org.apache.activemq.openwire.OpenWireFormat;
|
|
||||||
import org.apache.activemq.wireformat.WireFormat;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs against the broker but marshals all request and response commands.
|
|
||||||
*/
|
|
||||||
public class MarshallingBrokerTest extends BrokerTest {
|
|
||||||
|
|
||||||
public WireFormat wireFormat = new OpenWireFormat();
|
|
||||||
|
|
||||||
public void initCombos() {
|
|
||||||
|
|
||||||
OpenWireFormat wf1 = new OpenWireFormat();
|
|
||||||
wf1.setCacheEnabled(false);
|
|
||||||
OpenWireFormat wf2 = new OpenWireFormat();
|
|
||||||
wf2.setCacheEnabled(true);
|
|
||||||
|
|
||||||
addCombinationValues("wireFormat", new Object[]{wf1, wf2,});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected StubConnection createConnection() throws Exception {
|
|
||||||
return new StubConnection(broker) {
|
|
||||||
@Override
|
|
||||||
public Response request(Command command) throws Exception {
|
|
||||||
Response r = super.request((Command) wireFormat.unmarshal(wireFormat.marshal(command)));
|
|
||||||
if (r != null) {
|
|
||||||
r = (Response) wireFormat.unmarshal(wireFormat.marshal(r));
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void send(Command command) throws Exception {
|
|
||||||
super.send((Command) wireFormat.unmarshal(wireFormat.marshal(command)));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void dispatch(Command command) throws InterruptedException, IOException {
|
|
||||||
super.dispatch(wireFormat.unmarshal(wireFormat.marshal(command)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(MarshallingBrokerTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(suite());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,276 +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.broker;
|
|
||||||
|
|
||||||
import javax.jms.DeliveryMode;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.VMPendingSubscriberMessageStoragePolicy;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ConnectionInfo;
|
|
||||||
import org.apache.activemq.command.ConsumerInfo;
|
|
||||||
import org.apache.activemq.command.LocalTransactionId;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.command.MessageAck;
|
|
||||||
import org.apache.activemq.command.ProducerInfo;
|
|
||||||
import org.apache.activemq.command.SessionInfo;
|
|
||||||
|
|
||||||
public class MessageExpirationTest extends BrokerTestSupport {
|
|
||||||
|
|
||||||
public ActiveMQDestination destination;
|
|
||||||
public int deliveryMode = DeliveryMode.NON_PERSISTENT;
|
|
||||||
public int prefetch;
|
|
||||||
public byte destinationType = ActiveMQDestination.QUEUE_TYPE;
|
|
||||||
public boolean durableConsumer;
|
|
||||||
|
|
||||||
protected Message createMessage(ProducerInfo producerInfo,
|
|
||||||
ActiveMQDestination destination,
|
|
||||||
int deliveryMode,
|
|
||||||
int timeToLive) {
|
|
||||||
Message message = createMessage(producerInfo, destination, deliveryMode);
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
message.setTimestamp(now);
|
|
||||||
message.setExpiration(now + timeToLive);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initCombosForTestMessagesWaitingForUssageDecreaseExpire() {
|
|
||||||
addCombinationValues("deliveryMode", new Object[]{Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
|
||||||
addCombinationValues("destinationType", new Object[]{Byte.valueOf(ActiveMQDestination.TEMP_QUEUE_TYPE), Byte.valueOf(ActiveMQDestination.TEMP_TOPIC_TYPE), Byte.valueOf(ActiveMQDestination.QUEUE_TYPE), Byte.valueOf(ActiveMQDestination.TOPIC_TYPE)});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = new BrokerService();
|
|
||||||
broker.setPersistent(false);
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected PolicyEntry getDefaultPolicy() {
|
|
||||||
PolicyEntry policy = super.getDefaultPolicy();
|
|
||||||
// disable spooling
|
|
||||||
policy.setPendingSubscriberPolicy(new VMPendingSubscriberMessageStoragePolicy());
|
|
||||||
// have aggressive expiry period to ensure no deadlock or clash
|
|
||||||
policy.setExpireMessagesPeriod(100);
|
|
||||||
|
|
||||||
return policy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMessagesWaitingForUsageDecreaseExpire() throws Exception {
|
|
||||||
|
|
||||||
// Start a producer
|
|
||||||
final StubConnection connection = createConnection();
|
|
||||||
ConnectionInfo connectionInfo = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
final ProducerInfo producerInfo = createProducerInfo(sessionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
connection.send(producerInfo);
|
|
||||||
|
|
||||||
// Start a consumer..
|
|
||||||
final StubConnection connection2 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo2 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo2 = createSessionInfo(connectionInfo2);
|
|
||||||
connection2.send(connectionInfo2);
|
|
||||||
connection2.send(sessionInfo2);
|
|
||||||
|
|
||||||
destination = createDestinationInfo(connection2, connectionInfo2, destinationType);
|
|
||||||
ConsumerInfo consumerInfo2 = createConsumerInfo(sessionInfo2, destination);
|
|
||||||
consumerInfo2.setPrefetchSize(1);
|
|
||||||
connection2.request(consumerInfo2);
|
|
||||||
|
|
||||||
// Reduce the limit so that only 1 message can flow through the broker
|
|
||||||
// at a time.
|
|
||||||
broker.getSystemUsage().getMemoryUsage().setLimit(1);
|
|
||||||
|
|
||||||
final Message m1 = createMessage(producerInfo, destination, deliveryMode);
|
|
||||||
final Message m2 = createMessage(producerInfo, destination, deliveryMode, 1000);
|
|
||||||
final Message m3 = createMessage(producerInfo, destination, deliveryMode);
|
|
||||||
final Message m4 = createMessage(producerInfo, destination, deliveryMode, 1000);
|
|
||||||
|
|
||||||
// Produce in an async thread since the producer will be getting blocked
|
|
||||||
// by the usage manager..
|
|
||||||
new Thread() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// m1 and m3 should not expire.. but the others should.
|
|
||||||
try {
|
|
||||||
connection.send(m1);
|
|
||||||
connection.send(m2);
|
|
||||||
connection.send(m3);
|
|
||||||
connection.send(m4);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
|
|
||||||
// Make sure only 1 message was delivered due to prefetch == 1
|
|
||||||
Message m = receiveMessage(connection2);
|
|
||||||
assertNotNull(m);
|
|
||||||
assertEquals(m1.getMessageId(), m.getMessageId());
|
|
||||||
assertNoMessagesLeft(connection);
|
|
||||||
|
|
||||||
// Sleep before we ack so that the messages expire on the usage manager
|
|
||||||
Thread.sleep(1500);
|
|
||||||
connection2.send(createAck(consumerInfo2, m, 1, MessageAck.STANDARD_ACK_TYPE));
|
|
||||||
|
|
||||||
// 2nd message received should be m3.. it should have expired 2nd
|
|
||||||
// message sent.
|
|
||||||
m = receiveMessage(connection2);
|
|
||||||
assertNotNull(m);
|
|
||||||
assertEquals(m3.getMessageId(), m.getMessageId());
|
|
||||||
|
|
||||||
// Sleep before we ack so that the messages expire on the usage manager
|
|
||||||
Thread.sleep(1500);
|
|
||||||
connection2.send(createAck(consumerInfo2, m, 1, MessageAck.STANDARD_ACK_TYPE));
|
|
||||||
|
|
||||||
// And there should be no messages left now..
|
|
||||||
assertNoMessagesLeft(connection2);
|
|
||||||
|
|
||||||
connection.send(closeConnectionInfo(connectionInfo));
|
|
||||||
connection.send(closeConnectionInfo(connectionInfo2));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initCombosForTestMessagesInLongTransactionExpire() {
|
|
||||||
addCombinationValues("deliveryMode", new Object[]{Integer.valueOf(DeliveryMode.PERSISTENT), Integer.valueOf(DeliveryMode.NON_PERSISTENT)});
|
|
||||||
addCombinationValues("destinationType", new Object[]{Byte.valueOf(ActiveMQDestination.QUEUE_TYPE), Byte.valueOf(ActiveMQDestination.TOPIC_TYPE), Byte.valueOf(ActiveMQDestination.TEMP_QUEUE_TYPE), Byte.valueOf(ActiveMQDestination.TEMP_TOPIC_TYPE)});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMessagesInLongTransactionExpire() throws Exception {
|
|
||||||
|
|
||||||
// Start a producer and consumer
|
|
||||||
StubConnection connection = createConnection();
|
|
||||||
ConnectionInfo connectionInfo = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
ProducerInfo producerInfo = createProducerInfo(sessionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
connection.send(producerInfo);
|
|
||||||
|
|
||||||
destination = createDestinationInfo(connection, connectionInfo, destinationType);
|
|
||||||
|
|
||||||
ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
consumerInfo.setPrefetchSize(1000);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
// Start the tx..
|
|
||||||
LocalTransactionId txid = createLocalTransaction(sessionInfo);
|
|
||||||
connection.send(createBeginTransaction(connectionInfo, txid));
|
|
||||||
|
|
||||||
// m1 and m3 should not expire.. but the others should.
|
|
||||||
Message m1 = createMessage(producerInfo, destination, deliveryMode);
|
|
||||||
m1.setTransactionId(txid);
|
|
||||||
connection.send(m1);
|
|
||||||
Message m = createMessage(producerInfo, destination, deliveryMode, 1000);
|
|
||||||
m.setTransactionId(txid);
|
|
||||||
connection.send(m);
|
|
||||||
Message m3 = createMessage(producerInfo, destination, deliveryMode);
|
|
||||||
m3.setTransactionId(txid);
|
|
||||||
connection.send(m3);
|
|
||||||
m = createMessage(producerInfo, destination, deliveryMode, 1000);
|
|
||||||
m.setTransactionId(txid);
|
|
||||||
connection.send(m);
|
|
||||||
|
|
||||||
// Sleep before we commit so that the messages expire on the commit
|
|
||||||
// list..
|
|
||||||
Thread.sleep(1500);
|
|
||||||
connection.send(createCommitTransaction1Phase(connectionInfo, txid));
|
|
||||||
|
|
||||||
m = receiveMessage(connection);
|
|
||||||
assertNotNull(m);
|
|
||||||
assertEquals(m1.getMessageId(), m.getMessageId());
|
|
||||||
connection.send(createAck(consumerInfo, m, 1, MessageAck.STANDARD_ACK_TYPE));
|
|
||||||
|
|
||||||
// 2nd message received should be m3.. it should have expired 2nd
|
|
||||||
// message sent.
|
|
||||||
m = receiveMessage(connection);
|
|
||||||
assertNotNull(m);
|
|
||||||
assertEquals(m3.getMessageId(), m.getMessageId());
|
|
||||||
connection.send(createAck(consumerInfo, m, 1, MessageAck.STANDARD_ACK_TYPE));
|
|
||||||
|
|
||||||
// And there should be no messages left now..
|
|
||||||
assertNoMessagesLeft(connection);
|
|
||||||
|
|
||||||
connection.send(closeConnectionInfo(connectionInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initCombosForTestMessagesInSubscriptionPendingListExpire() {
|
|
||||||
addCombinationValues("deliveryMode", new Object[]{Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
|
||||||
addCombinationValues("destinationType", new Object[]{Byte.valueOf(ActiveMQDestination.QUEUE_TYPE), Byte.valueOf(ActiveMQDestination.TOPIC_TYPE), Byte.valueOf(ActiveMQDestination.TEMP_QUEUE_TYPE), Byte.valueOf(ActiveMQDestination.TEMP_TOPIC_TYPE)});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMessagesInSubscriptionPendingListExpire() throws Exception {
|
|
||||||
|
|
||||||
// Start a producer and consumer
|
|
||||||
StubConnection connection = createConnection();
|
|
||||||
ConnectionInfo connectionInfo = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
ProducerInfo producerInfo = createProducerInfo(sessionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
connection.send(producerInfo);
|
|
||||||
|
|
||||||
destination = createDestinationInfo(connection, connectionInfo, destinationType);
|
|
||||||
|
|
||||||
ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
consumerInfo.setPrefetchSize(1);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
// m1 and m3 should not expire.. but the others should.
|
|
||||||
Message m1 = createMessage(producerInfo, destination, deliveryMode);
|
|
||||||
connection.send(m1);
|
|
||||||
connection.send(createMessage(producerInfo, destination, deliveryMode, 1000));
|
|
||||||
Message m3 = createMessage(producerInfo, destination, deliveryMode);
|
|
||||||
connection.send(m3);
|
|
||||||
connection.send(createMessage(producerInfo, destination, deliveryMode, 1000));
|
|
||||||
|
|
||||||
// Make sure only 1 message was delivered due to prefetch == 1
|
|
||||||
Message m = receiveMessage(connection);
|
|
||||||
assertNotNull(m);
|
|
||||||
assertEquals(m1.getMessageId(), m.getMessageId());
|
|
||||||
assertNoMessagesLeft(connection);
|
|
||||||
|
|
||||||
// Sleep before we ack so that the messages expire on the pending list..
|
|
||||||
Thread.sleep(1500);
|
|
||||||
connection.send(createAck(consumerInfo, m, 1, MessageAck.STANDARD_ACK_TYPE));
|
|
||||||
|
|
||||||
// 2nd message received should be m3.. it should have expired 2nd
|
|
||||||
// message sent.
|
|
||||||
m = receiveMessage(connection);
|
|
||||||
assertNotNull(m);
|
|
||||||
assertEquals(m3.getMessageId(), m.getMessageId());
|
|
||||||
connection.send(createAck(consumerInfo, m, 1, MessageAck.STANDARD_ACK_TYPE));
|
|
||||||
|
|
||||||
// And there should be no messages left now..
|
|
||||||
assertNoMessagesLeft(connection);
|
|
||||||
|
|
||||||
connection.send(closeConnectionInfo(connectionInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(MessageExpirationTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(suite());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,132 +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.broker;
|
|
||||||
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
import javax.jms.ExceptionListener;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
@RunWith(BlockJUnit4ClassRunner.class)
|
|
||||||
public class NioQueueSubscriptionTest extends QueueSubscriptionTest {
|
|
||||||
|
|
||||||
protected static final Logger LOG = LoggerFactory.getLogger(NioQueueSubscriptionTest.class);
|
|
||||||
|
|
||||||
private final Map<Thread, Throwable> exceptions = Collections.synchronizedMap(new HashMap<Thread, Throwable>());
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
return new ActiveMQConnectionFactory("tcp://localhost:62621?trace=false");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService answer = BrokerFactory.createBroker(new URI("broker://nio://localhost:62621?useQueueForAccept=false&persistent=false&wiewformat.maxInactivityDuration=0"));
|
|
||||||
answer.getManagementContext().setCreateConnector(false);
|
|
||||||
answer.setUseJmx(false);
|
|
||||||
answer.setDeleteAllMessagesOnStartup(true);
|
|
||||||
final List<PolicyEntry> policyEntries = new ArrayList<>();
|
|
||||||
final PolicyEntry entry = new PolicyEntry();
|
|
||||||
entry.setQueue(">");
|
|
||||||
entry.setOptimizedDispatch(true);
|
|
||||||
policyEntries.add(entry);
|
|
||||||
|
|
||||||
final PolicyMap policyMap = new PolicyMap();
|
|
||||||
policyMap.setPolicyEntries(policyEntries);
|
|
||||||
answer.setDestinationPolicy(policyMap);
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore("See AMQ-4286")
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testLotsOfConcurrentConnections() throws Exception {
|
|
||||||
ExecutorService executor = Executors.newCachedThreadPool();
|
|
||||||
final ConnectionFactory factory = createConnectionFactory();
|
|
||||||
int connectionCount = 400;
|
|
||||||
final AtomicInteger threadId = new AtomicInteger(0);
|
|
||||||
for (int i = 0; i < connectionCount; i++) {
|
|
||||||
executor.execute(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
final int innerId = threadId.incrementAndGet();
|
|
||||||
try {
|
|
||||||
ExceptionListener listener = new NioQueueSubscriptionTestListener(innerId, exceptions, LOG);
|
|
||||||
ActiveMQConnection connection = (ActiveMQConnection) factory.createConnection();
|
|
||||||
connection.setExceptionListener(listener);
|
|
||||||
connection.start();
|
|
||||||
assertNotNull(connection.getBrokerName());
|
|
||||||
connections.add(connection);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error(">>>> Exception in run() on thread " + innerId, e);
|
|
||||||
exceptions.put(Thread.currentThread(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
executor.shutdown();
|
|
||||||
executor.awaitTermination(30, TimeUnit.SECONDS);
|
|
||||||
|
|
||||||
if (!exceptions.isEmpty()) {
|
|
||||||
LOG.error(">>>> " + exceptions.size() + " exceptions like", exceptions.values().iterator().next());
|
|
||||||
fail("unexpected exceptions in worker threads: " + exceptions.values().iterator().next());
|
|
||||||
}
|
|
||||||
LOG.info("created " + connectionCount + " connections");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NioQueueSubscriptionTestListener implements ExceptionListener {
|
|
||||||
|
|
||||||
private int id = 0;
|
|
||||||
protected Logger LOG;
|
|
||||||
private final Map<Thread, Throwable> exceptions;
|
|
||||||
|
|
||||||
public NioQueueSubscriptionTestListener(int id, Map<Thread, Throwable> exceptions, Logger log) {
|
|
||||||
this.id = id;
|
|
||||||
this.exceptions = exceptions;
|
|
||||||
this.LOG = log;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onException(JMSException exception) {
|
|
||||||
LOG.error(">>>> Exception in onException() on thread " + id, exception);
|
|
||||||
exceptions.put(Thread.currentThread(), exception);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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.broker;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
// https://issues.apache.org/activemq/browse/AMQ-2939
|
|
||||||
public class OutOfOrderXMLTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void verifyBrokerCreationWhenXmlOutOfOrderValidationFalse() throws Exception {
|
|
||||||
BrokerService answer = BrokerFactory.createBroker(new URI("xbean:org/apache/activemq/broker/out-of-order-broker-elements.xml?validate=false"));
|
|
||||||
answer.stop();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,123 +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.broker;
|
|
||||||
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.activemq.TestSupport;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.util.JMXSupport;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@RunWith(value = Parameterized.class)
|
|
||||||
public class QueueMbeanRestartTest extends TestSupport {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(QueueMbeanRestartTest.class);
|
|
||||||
|
|
||||||
BrokerService broker;
|
|
||||||
|
|
||||||
private final TestSupport.PersistenceAdapterChoice persistenceAdapterChoice;
|
|
||||||
|
|
||||||
@Parameterized.Parameters
|
|
||||||
public static Collection<TestSupport.PersistenceAdapterChoice[]> getTestParameters() {
|
|
||||||
TestSupport.PersistenceAdapterChoice[] kahaDb = {TestSupport.PersistenceAdapterChoice.KahaDB};
|
|
||||||
TestSupport.PersistenceAdapterChoice[] levelDb = {TestSupport.PersistenceAdapterChoice.LevelDB};
|
|
||||||
TestSupport.PersistenceAdapterChoice[] jdbc = {TestSupport.PersistenceAdapterChoice.JDBC};
|
|
||||||
List<TestSupport.PersistenceAdapterChoice[]> choices = new ArrayList<>();
|
|
||||||
choices.add(kahaDb);
|
|
||||||
choices.add(levelDb);
|
|
||||||
choices.add(jdbc);
|
|
||||||
|
|
||||||
return choices;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QueueMbeanRestartTest(TestSupport.PersistenceAdapterChoice choice) {
|
|
||||||
this.persistenceAdapterChoice = choice;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
topic = false;
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
broker.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 60000)
|
|
||||||
public void testMBeanPresenceOnRestart() throws Exception {
|
|
||||||
createBroker(true);
|
|
||||||
|
|
||||||
sendMessages();
|
|
||||||
verifyPresenceOfQueueMbean();
|
|
||||||
LOG.info("restart....");
|
|
||||||
|
|
||||||
restartBroker();
|
|
||||||
verifyPresenceOfQueueMbean();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void restartBroker() throws Exception {
|
|
||||||
broker.stop();
|
|
||||||
broker.waitUntilStopped();
|
|
||||||
Thread.sleep(5 * 1000);
|
|
||||||
createBroker(false);
|
|
||||||
broker.waitUntilStarted();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void verifyPresenceOfQueueMbean() throws Exception {
|
|
||||||
for (ObjectName name : broker.getManagementContext().queryNames(null, null)) {
|
|
||||||
LOG.info("candidate :" + name);
|
|
||||||
String type = name.getKeyProperty("destinationType");
|
|
||||||
if (type != null && type.equals("Queue")) {
|
|
||||||
assertEquals(JMXSupport.encodeObjectNamePart(((ActiveMQQueue) createDestination()).getPhysicalName()), name.getKeyProperty("destinationName"));
|
|
||||||
LOG.info("found mbbean " + name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fail("expected to find matching queue mbean for: " + createDestination());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendMessages() throws Exception {
|
|
||||||
Session session = createConnection().createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageProducer producer = session.createProducer(createDestination());
|
|
||||||
producer.send(session.createTextMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createBroker(boolean deleteAll) throws Exception {
|
|
||||||
broker = new BrokerService();
|
|
||||||
setPersistenceAdapter(broker, persistenceAdapterChoice);
|
|
||||||
|
|
||||||
broker.setDeleteAllMessagesOnStartup(deleteAll);
|
|
||||||
broker.start();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,188 +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.broker;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.JmsMultipleClientsTestSupport;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
|
||||||
|
|
||||||
@RunWith(BlockJUnit4ClassRunner.class)
|
|
||||||
public class QueueSubscriptionTest extends JmsMultipleClientsTestSupport {
|
|
||||||
|
|
||||||
protected int messageCount = 1000; // 1000 Messages per producer
|
|
||||||
protected int prefetchCount = 10;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
@Override
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
durable = false;
|
|
||||||
topic = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
@Override
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testManyProducersOneConsumer() throws Exception {
|
|
||||||
consumerCount = 1;
|
|
||||||
producerCount = 10;
|
|
||||||
messageCount = 100;
|
|
||||||
messageSize = 1; // 1 byte
|
|
||||||
prefetchCount = 10;
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersSmallMessagesOnePrefetch() throws Exception {
|
|
||||||
consumerCount = 2;
|
|
||||||
producerCount = 1;
|
|
||||||
messageCount = 1000;
|
|
||||||
messageSize = 1024; // 1 Kb
|
|
||||||
configurePrefetchOfOne();
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersSmallMessagesLargePrefetch() throws Exception {
|
|
||||||
consumerCount = 2;
|
|
||||||
producerCount = 1;
|
|
||||||
messageCount = 1000;
|
|
||||||
prefetchCount = messageCount * 2;
|
|
||||||
messageSize = 1024; // 1 Kb
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 2 * 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersLargeMessagesOnePrefetch() throws Exception {
|
|
||||||
consumerCount = 2;
|
|
||||||
producerCount = 1;
|
|
||||||
messageCount = 10;
|
|
||||||
messageSize = 1024 * 1024 * 1; // 2 MB
|
|
||||||
configurePrefetchOfOne();
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersLargeMessagesLargePrefetch() throws Exception {
|
|
||||||
consumerCount = 2;
|
|
||||||
producerCount = 1;
|
|
||||||
messageCount = 10;
|
|
||||||
prefetchCount = messageCount * 2;
|
|
||||||
messageSize = 1024 * 1024 * 1; // 2 MB
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerManyConsumersFewMessages() throws Exception {
|
|
||||||
consumerCount = 50;
|
|
||||||
producerCount = 1;
|
|
||||||
messageCount = 10;
|
|
||||||
messageSize = 1; // 1 byte
|
|
||||||
prefetchCount = 10;
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerManyConsumersManyMessages() throws Exception {
|
|
||||||
consumerCount = 50;
|
|
||||||
producerCount = 1;
|
|
||||||
messageCount = 1000;
|
|
||||||
messageSize = 1; // 1 byte
|
|
||||||
prefetchCount = messageCount / consumerCount;
|
|
||||||
allMessagesList.setMaximumDuration(allMessagesList.getMaximumDuration() * 20);
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 2 * 60 * 1000)
|
|
||||||
public void testManyProducersManyConsumers() throws Exception {
|
|
||||||
consumerCount = 200;
|
|
||||||
producerCount = 50;
|
|
||||||
messageCount = 100;
|
|
||||||
messageSize = 1; // 1 byte
|
|
||||||
prefetchCount = 100;
|
|
||||||
allMessagesList.setMaximumDuration(allMessagesList.getMaximumDuration() * 20);
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void configurePrefetchOfOne() {
|
|
||||||
prefetchCount = 1;
|
|
||||||
|
|
||||||
// this is gonna be a bit slow what with the low prefetch so bump up the
|
|
||||||
// wait time
|
|
||||||
allMessagesList.setMaximumDuration(allMessagesList.getMaximumDuration() * 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doMultipleClientsTest() throws Exception {
|
|
||||||
// Create destination
|
|
||||||
final ActiveMQDestination dest = createDestination();
|
|
||||||
|
|
||||||
// Create consumers
|
|
||||||
ActiveMQConnectionFactory consumerFactory = (ActiveMQConnectionFactory) createConnectionFactory();
|
|
||||||
consumerFactory.getPrefetchPolicy().setAll(prefetchCount);
|
|
||||||
|
|
||||||
startConsumers(consumerFactory, dest);
|
|
||||||
|
|
||||||
startProducers(dest, messageCount);
|
|
||||||
|
|
||||||
// Wait for messages to be received. Make it proportional to the
|
|
||||||
// messages delivered.
|
|
||||||
int totalMessageCount = messageCount * producerCount;
|
|
||||||
if (dest.isTopic()) {
|
|
||||||
totalMessageCount *= consumerCount;
|
|
||||||
}
|
|
||||||
waitForAllMessagesToBeReceived(totalMessageCount);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,95 +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.broker;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ReconnectWithJMXEnabledTest extends EmbeddedBrokerTestSupport {
|
|
||||||
|
|
||||||
protected Connection connection;
|
|
||||||
protected boolean transacted;
|
|
||||||
protected int authMode = Session.AUTO_ACKNOWLEDGE;
|
|
||||||
|
|
||||||
public void testTestUseConnectionCloseBrokerThenRestartInSameJVM() throws Exception {
|
|
||||||
connection = connectionFactory.createConnection();
|
|
||||||
useConnection(connection);
|
|
||||||
connection.close();
|
|
||||||
|
|
||||||
broker.stop();
|
|
||||||
broker = createBroker();
|
|
||||||
startBroker();
|
|
||||||
|
|
||||||
connectionFactory = createConnectionFactory();
|
|
||||||
connection = connectionFactory.createConnection();
|
|
||||||
useConnection(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
bindAddress = "tcp://localhost:0";
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
return new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getPublishableConnectString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
if (connection != null) {
|
|
||||||
connection.close();
|
|
||||||
connection = null;
|
|
||||||
}
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService answer = new BrokerService();
|
|
||||||
answer.setUseJmx(true);
|
|
||||||
answer.setPersistent(isPersistent());
|
|
||||||
answer.addConnector(bindAddress);
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void useConnection(Connection connection) throws Exception {
|
|
||||||
connection.setClientID("foo");
|
|
||||||
connection.start();
|
|
||||||
Session session = connection.createSession(transacted, authMode);
|
|
||||||
Destination destination = createDestination();
|
|
||||||
MessageConsumer consumer = session.createConsumer(destination);
|
|
||||||
MessageProducer producer = session.createProducer(destination);
|
|
||||||
Message message = session.createTextMessage("Hello World");
|
|
||||||
producer.send(message);
|
|
||||||
Thread.sleep(1000);
|
|
||||||
consumer.close();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,580 +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.broker;
|
|
||||||
|
|
||||||
import javax.jms.DeliveryMode;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
|
||||||
import org.apache.activemq.command.ConnectionInfo;
|
|
||||||
import org.apache.activemq.command.ConsumerInfo;
|
|
||||||
import org.apache.activemq.command.LocalTransactionId;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.command.MessageAck;
|
|
||||||
import org.apache.activemq.command.MessageId;
|
|
||||||
import org.apache.activemq.command.ProducerInfo;
|
|
||||||
import org.apache.activemq.command.SessionInfo;
|
|
||||||
import org.apache.activemq.command.XATransactionId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to simulate the recovery that occurs when a broker shuts down.
|
|
||||||
*/
|
|
||||||
public class RecoveryBrokerTest extends BrokerRestartTestSupport {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to verify that after a broker restart durable subscriptions that use
|
|
||||||
* wild cards are still wild card subscription after broker restart.
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
//need to revist!!!
|
|
||||||
public void XtestWildCardSubscriptionPreservedOnRestart() throws Exception {
|
|
||||||
ActiveMQDestination dest1 = new ActiveMQTopic("TEST.A");
|
|
||||||
ActiveMQDestination dest2 = new ActiveMQTopic("TEST.B");
|
|
||||||
ActiveMQDestination dest3 = new ActiveMQTopic("TEST.C");
|
|
||||||
ActiveMQDestination wildDest = new ActiveMQTopic("TEST.>");
|
|
||||||
|
|
||||||
ArrayList<MessageId> sentBeforeRestart = new ArrayList<>();
|
|
||||||
ArrayList<MessageId> sentBeforeCreateConsumer = new ArrayList<>();
|
|
||||||
ArrayList<MessageId> sentAfterCreateConsumer = new ArrayList<>();
|
|
||||||
|
|
||||||
// Setup a first connection
|
|
||||||
{
|
|
||||||
StubConnection connection1 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo1 = createConnectionInfo();
|
|
||||||
connectionInfo1.setClientId("A");
|
|
||||||
SessionInfo sessionInfo1 = createSessionInfo(connectionInfo1);
|
|
||||||
ProducerInfo producerInfo1 = createProducerInfo(sessionInfo1);
|
|
||||||
connection1.send(connectionInfo1);
|
|
||||||
connection1.send(sessionInfo1);
|
|
||||||
connection1.send(producerInfo1);
|
|
||||||
|
|
||||||
// Create the durable subscription.
|
|
||||||
ConsumerInfo consumerInfo1 = createConsumerInfo(sessionInfo1, wildDest);
|
|
||||||
consumerInfo1.setSubscriptionName("test");
|
|
||||||
consumerInfo1.setPrefetchSize(100);
|
|
||||||
connection1.send(consumerInfo1);
|
|
||||||
|
|
||||||
// Close the subscription.
|
|
||||||
connection1.send(closeConsumerInfo(consumerInfo1));
|
|
||||||
|
|
||||||
// Send the messages
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message m = createMessage(producerInfo1, dest1, DeliveryMode.PERSISTENT);
|
|
||||||
connection1.send(m);
|
|
||||||
sentBeforeRestart.add(m.getMessageId());
|
|
||||||
}
|
|
||||||
connection1.request(closeConnectionInfo(connectionInfo1));
|
|
||||||
connection1.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restart the broker.
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// Get a connection to the new broker.
|
|
||||||
{
|
|
||||||
StubConnection connection2 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo2 = createConnectionInfo();
|
|
||||||
connectionInfo2.setClientId("A");
|
|
||||||
SessionInfo sessionInfo2 = createSessionInfo(connectionInfo2);
|
|
||||||
connection2.send(connectionInfo2);
|
|
||||||
connection2.send(sessionInfo2);
|
|
||||||
|
|
||||||
ProducerInfo producerInfo2 = createProducerInfo(sessionInfo2);
|
|
||||||
connection2.send(producerInfo2);
|
|
||||||
|
|
||||||
// Send messages before the durable subscription is re-activated.
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message m = createMessage(producerInfo2, dest2, DeliveryMode.PERSISTENT);
|
|
||||||
connection2.send(m);
|
|
||||||
sentBeforeCreateConsumer.add(m.getMessageId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-open the subscription.
|
|
||||||
ConsumerInfo consumerInfo2 = createConsumerInfo(sessionInfo2, wildDest);
|
|
||||||
consumerInfo2.setSubscriptionName("test");
|
|
||||||
consumerInfo2.setPrefetchSize(100);
|
|
||||||
connection2.send(consumerInfo2);
|
|
||||||
|
|
||||||
// Send messages after the subscription is activated.
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message m = createMessage(producerInfo2, dest3, DeliveryMode.PERSISTENT);
|
|
||||||
connection2.send(m);
|
|
||||||
sentAfterCreateConsumer.add(m.getMessageId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// We should get the recovered messages...
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message m2 = receiveMessage(connection2);
|
|
||||||
assertNotNull("Recovered message missing: " + i, m2);
|
|
||||||
assertEquals(sentBeforeRestart.get(i), m2.getMessageId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// We should get get the messages that were sent before the sub was
|
|
||||||
// reactivated.
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message m2 = receiveMessage(connection2);
|
|
||||||
assertNotNull("Before activated message missing: " + i, m2);
|
|
||||||
assertEquals(sentBeforeCreateConsumer.get(i), m2.getMessageId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// We should get get the messages that were sent after the sub was
|
|
||||||
// reactivated.
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message m2 = receiveMessage(connection2);
|
|
||||||
assertNotNull("After activated message missing: " + i, m2);
|
|
||||||
assertEquals("" + i, sentAfterCreateConsumer.get(i), m2.getMessageId());
|
|
||||||
}
|
|
||||||
|
|
||||||
assertNoMessagesLeft(connection2);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testConsumedQueuePersistentMessagesLostOnRestart() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination destination = new ActiveMQQueue("TEST");
|
|
||||||
|
|
||||||
// Setup the producer and send the message.
|
|
||||||
StubConnection connection = createConnection();
|
|
||||||
ConnectionInfo connectionInfo = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
ProducerInfo producerInfo = createProducerInfo(sessionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
connection.send(producerInfo);
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message message = createMessage(producerInfo, destination);
|
|
||||||
message.setPersistent(true);
|
|
||||||
connection.send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the consumer and receive the message.
|
|
||||||
connection = createConnection();
|
|
||||||
connectionInfo = createConnectionInfo();
|
|
||||||
sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
// The we should get the messages.
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message m2 = receiveMessage(connection);
|
|
||||||
assertNotNull(m2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// restart the broker.
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// No messages should be delivered.
|
|
||||||
Message m = receiveMessage(connection);
|
|
||||||
assertNull(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testQueuePersistentUncommitedMessagesLostOnRestart() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination destination = new ActiveMQQueue("TEST");
|
|
||||||
|
|
||||||
// Setup the producer and send the message.
|
|
||||||
StubConnection connection = createConnection();
|
|
||||||
ConnectionInfo connectionInfo = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
ProducerInfo producerInfo = createProducerInfo(sessionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
connection.send(producerInfo);
|
|
||||||
|
|
||||||
// Begin the transaction.
|
|
||||||
LocalTransactionId txid = createLocalTransaction(sessionInfo);
|
|
||||||
connection.send(createBeginTransaction(connectionInfo, txid));
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message message = createMessage(producerInfo, destination);
|
|
||||||
message.setPersistent(true);
|
|
||||||
message.setTransactionId(txid);
|
|
||||||
connection.send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't commit
|
|
||||||
|
|
||||||
// restart the broker.
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// Setup the consumer and receive the message.
|
|
||||||
connection = createConnection();
|
|
||||||
connectionInfo = createConnectionInfo();
|
|
||||||
sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
// No messages should be delivered.
|
|
||||||
Message m = receiveMessage(connection);
|
|
||||||
assertNull(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testTopicDurableConsumerHoldsPersistentMessageAfterRestart() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination destination = new ActiveMQTopic("TEST");
|
|
||||||
|
|
||||||
// Setup a first connection
|
|
||||||
StubConnection connection1 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo1 = createConnectionInfo();
|
|
||||||
connectionInfo1.setClientId("A");
|
|
||||||
SessionInfo sessionInfo1 = createSessionInfo(connectionInfo1);
|
|
||||||
ProducerInfo producerInfo1 = createProducerInfo(sessionInfo1);
|
|
||||||
connection1.send(connectionInfo1);
|
|
||||||
connection1.send(sessionInfo1);
|
|
||||||
connection1.send(producerInfo1);
|
|
||||||
|
|
||||||
// Create the durable subscription.
|
|
||||||
ConsumerInfo consumerInfo1 = createConsumerInfo(sessionInfo1, destination);
|
|
||||||
consumerInfo1.setSubscriptionName("test");
|
|
||||||
consumerInfo1.setPrefetchSize(100);
|
|
||||||
connection1.send(consumerInfo1);
|
|
||||||
|
|
||||||
// Close the subscription.
|
|
||||||
connection1.send(closeConsumerInfo(consumerInfo1));
|
|
||||||
|
|
||||||
// Send the messages
|
|
||||||
connection1.send(createMessage(producerInfo1, destination, DeliveryMode.PERSISTENT));
|
|
||||||
connection1.send(createMessage(producerInfo1, destination, DeliveryMode.PERSISTENT));
|
|
||||||
connection1.send(createMessage(producerInfo1, destination, DeliveryMode.PERSISTENT));
|
|
||||||
connection1.send(createMessage(producerInfo1, destination, DeliveryMode.PERSISTENT));
|
|
||||||
connection1.request(closeConnectionInfo(connectionInfo1));
|
|
||||||
// Restart the broker.
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// Get a connection to the new broker.
|
|
||||||
StubConnection connection2 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo2 = createConnectionInfo();
|
|
||||||
connectionInfo2.setClientId("A");
|
|
||||||
SessionInfo sessionInfo2 = createSessionInfo(connectionInfo2);
|
|
||||||
connection2.send(connectionInfo2);
|
|
||||||
connection2.send(sessionInfo2);
|
|
||||||
|
|
||||||
// Re-open the subscription.
|
|
||||||
ConsumerInfo consumerInfo2 = createConsumerInfo(sessionInfo2, destination);
|
|
||||||
consumerInfo2.setSubscriptionName("test");
|
|
||||||
consumerInfo2.setPrefetchSize(100);
|
|
||||||
connection2.send(consumerInfo2);
|
|
||||||
|
|
||||||
// The we should get the messages.
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message m2 = receiveMessage(connection2);
|
|
||||||
assertNotNull("Did not get message " + i, m2);
|
|
||||||
}
|
|
||||||
assertNoMessagesLeft(connection2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testQueuePersistentMessagesNotLostOnRestart() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination destination = new ActiveMQQueue("TEST");
|
|
||||||
|
|
||||||
// Setup the producer and send the message.
|
|
||||||
StubConnection connection = createConnection();
|
|
||||||
ConnectionInfo connectionInfo = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
ProducerInfo producerInfo = createProducerInfo(sessionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
connection.send(producerInfo);
|
|
||||||
Message message = createMessage(producerInfo, destination);
|
|
||||||
message.setPersistent(true);
|
|
||||||
connection.send(message);
|
|
||||||
connection.request(closeConnectionInfo(connectionInfo));
|
|
||||||
|
|
||||||
// restart the broker.
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// Setup the consumer and receive the message.
|
|
||||||
connection = createConnection();
|
|
||||||
connectionInfo = createConnectionInfo();
|
|
||||||
sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
// Message should have been dropped due to broker restart.
|
|
||||||
Message m = receiveMessage(connection);
|
|
||||||
assertNotNull("Should have received a message by now!", m);
|
|
||||||
assertEquals(m.getMessageId(), message.getMessageId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testQueueNonPersistentMessagesLostOnRestart() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination destination = new ActiveMQQueue("TEST");
|
|
||||||
|
|
||||||
// Setup the producer and send the message.
|
|
||||||
StubConnection connection = createConnection();
|
|
||||||
ConnectionInfo connectionInfo = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
ProducerInfo producerInfo = createProducerInfo(sessionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
connection.send(producerInfo);
|
|
||||||
Message message = createMessage(producerInfo, destination);
|
|
||||||
message.setPersistent(false);
|
|
||||||
connection.send(message);
|
|
||||||
|
|
||||||
// restart the broker.
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// Setup the consumer and receive the message.
|
|
||||||
connection = createConnection();
|
|
||||||
connectionInfo = createConnectionInfo();
|
|
||||||
sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
// Message should have been dropped due to broker restart.
|
|
||||||
assertNoMessagesLeft(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testQueuePersistentCommittedMessagesNotLostOnRestart() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination destination = new ActiveMQQueue("TEST");
|
|
||||||
|
|
||||||
// Setup the producer and send the message.
|
|
||||||
StubConnection connection = createConnection();
|
|
||||||
ConnectionInfo connectionInfo = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
ProducerInfo producerInfo = createProducerInfo(sessionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
connection.send(producerInfo);
|
|
||||||
|
|
||||||
// Begin the transaction.
|
|
||||||
LocalTransactionId txid = createLocalTransaction(sessionInfo);
|
|
||||||
connection.send(createBeginTransaction(connectionInfo, txid));
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message message = createMessage(producerInfo, destination);
|
|
||||||
message.setPersistent(true);
|
|
||||||
message.setTransactionId(txid);
|
|
||||||
connection.send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commit
|
|
||||||
connection.send(createCommitTransaction1Phase(connectionInfo, txid));
|
|
||||||
connection.request(closeConnectionInfo(connectionInfo));
|
|
||||||
// restart the broker.
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// Setup the consumer and receive the message.
|
|
||||||
connection = createConnection();
|
|
||||||
connectionInfo = createConnectionInfo();
|
|
||||||
sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message m = receiveMessage(connection);
|
|
||||||
assertNotNull(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertNoMessagesLeft(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testQueuePersistentCommittedAcksNotLostOnRestart() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination destination = new ActiveMQQueue("TEST");
|
|
||||||
|
|
||||||
// Setup the producer and send the message.
|
|
||||||
StubConnection connection = createConnection();
|
|
||||||
ConnectionInfo connectionInfo = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
ProducerInfo producerInfo = createProducerInfo(sessionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
connection.send(producerInfo);
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message message = createMessage(producerInfo, destination);
|
|
||||||
message.setPersistent(true);
|
|
||||||
connection.send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the consumer and receive the message.
|
|
||||||
ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
// Begin the transaction.
|
|
||||||
LocalTransactionId txid = createLocalTransaction(sessionInfo);
|
|
||||||
connection.send(createBeginTransaction(connectionInfo, txid));
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message m = receiveMessage(connection);
|
|
||||||
assertNotNull(m);
|
|
||||||
MessageAck ack = createAck(consumerInfo, m, 1, MessageAck.STANDARD_ACK_TYPE);
|
|
||||||
ack.setTransactionId(txid);
|
|
||||||
connection.send(ack);
|
|
||||||
}
|
|
||||||
// Commit
|
|
||||||
connection.send(createCommitTransaction1Phase(connectionInfo, txid));
|
|
||||||
connection.request(closeConnectionInfo(connectionInfo));
|
|
||||||
// restart the broker.
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// Setup the consumer and receive the message.
|
|
||||||
connection = createConnection();
|
|
||||||
connectionInfo = createConnectionInfo();
|
|
||||||
sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
// No messages should be delivered.
|
|
||||||
Message m = receiveMessage(connection);
|
|
||||||
assertNull(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testQueuePersistentUncommitedAcksLostOnRestart() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination destination = new ActiveMQQueue("TEST");
|
|
||||||
|
|
||||||
// Setup the producer and send the message.
|
|
||||||
StubConnection connection = createConnection();
|
|
||||||
ConnectionInfo connectionInfo = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
ProducerInfo producerInfo = createProducerInfo(sessionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
connection.send(producerInfo);
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message message = createMessage(producerInfo, destination);
|
|
||||||
message.setPersistent(true);
|
|
||||||
connection.send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the consumer and receive the message.
|
|
||||||
ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
// Begin the transaction.
|
|
||||||
LocalTransactionId txid = createLocalTransaction(sessionInfo);
|
|
||||||
connection.send(createBeginTransaction(connectionInfo, txid));
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message m = receiveMessage(connection);
|
|
||||||
assertNotNull(m);
|
|
||||||
MessageAck ack = createAck(consumerInfo, m, 1, MessageAck.STANDARD_ACK_TYPE);
|
|
||||||
ack.setTransactionId(txid);
|
|
||||||
connection.send(ack);
|
|
||||||
}
|
|
||||||
// Don't commit
|
|
||||||
|
|
||||||
// restart the broker.
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// Setup the consumer and receive the message.
|
|
||||||
connection = createConnection();
|
|
||||||
connectionInfo = createConnectionInfo();
|
|
||||||
sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
// All messages should be re-delivered.
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Message m = receiveMessage(connection);
|
|
||||||
assertNotNull(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertNoMessagesLeft(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testQueuePersistentXAUncommitedAcksLostOnRestart() throws Exception {
|
|
||||||
int NUMBER = 100;
|
|
||||||
ActiveMQDestination destination = new ActiveMQQueue("TEST");
|
|
||||||
|
|
||||||
// Setup the producer and send the message.
|
|
||||||
StubConnection connection = createConnection();
|
|
||||||
ConnectionInfo connectionInfo = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
ProducerInfo producerInfo = createProducerInfo(sessionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
connection.send(producerInfo);
|
|
||||||
|
|
||||||
for (int i = 0; i < NUMBER; i++) {
|
|
||||||
Message message = createMessage(producerInfo, destination);
|
|
||||||
message.setPersistent(true);
|
|
||||||
connection.send(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the consumer and receive the message.
|
|
||||||
ConsumerInfo consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
// Begin the transaction.
|
|
||||||
XATransactionId txid = createXATransaction(sessionInfo);
|
|
||||||
connection.send(createBeginTransaction(connectionInfo, txid));
|
|
||||||
Message m = null;
|
|
||||||
for (int i = 0; i < NUMBER; i++) {
|
|
||||||
m = receiveMessage(connection);
|
|
||||||
assertNotNull(m);
|
|
||||||
}
|
|
||||||
MessageAck ack = createAck(consumerInfo, m, NUMBER, MessageAck.STANDARD_ACK_TYPE);
|
|
||||||
ack.setTransactionId(txid);
|
|
||||||
connection.send(ack);
|
|
||||||
|
|
||||||
// Don't commit
|
|
||||||
|
|
||||||
// restart the broker.
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// Setup the consumer and receive the message.
|
|
||||||
connection = createConnection();
|
|
||||||
connectionInfo = createConnectionInfo();
|
|
||||||
sessionInfo = createSessionInfo(connectionInfo);
|
|
||||||
connection.send(connectionInfo);
|
|
||||||
connection.send(sessionInfo);
|
|
||||||
consumerInfo = createConsumerInfo(sessionInfo, destination);
|
|
||||||
connection.send(consumerInfo);
|
|
||||||
|
|
||||||
// All messages should be re-delivered.
|
|
||||||
for (int i = 0; i < NUMBER; i++) {
|
|
||||||
m = receiveMessage(connection);
|
|
||||||
assertNotNull(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertNoMessagesLeft(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(RecoveryBrokerTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(suite());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,293 +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.broker;
|
|
||||||
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TextMessage;
|
|
||||||
import javax.jms.TopicSubscriber;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.TestSupport;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
|
||||||
import org.apache.activemq.transport.failover.FailoverTransport;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@RunWith(value = Parameterized.class)
|
|
||||||
public class RedeliveryRestartTest extends TestSupport {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(RedeliveryRestartTest.class);
|
|
||||||
ActiveMQConnection connection;
|
|
||||||
BrokerService broker = null;
|
|
||||||
String queueName = "redeliveryRestartQ";
|
|
||||||
|
|
||||||
@Parameterized.Parameter
|
|
||||||
public TestSupport.PersistenceAdapterChoice persistenceAdapterChoice = PersistenceAdapterChoice.KahaDB;
|
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "Store={0}")
|
|
||||||
public static Iterable<Object[]> data() {
|
|
||||||
return Arrays.asList(new Object[][]{{TestSupport.PersistenceAdapterChoice.KahaDB}, {TestSupport.PersistenceAdapterChoice.JDBC}, {TestSupport.PersistenceAdapterChoice.LevelDB}});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
broker = new BrokerService();
|
|
||||||
configureBroker(broker);
|
|
||||||
broker.setDeleteAllMessagesOnStartup(true);
|
|
||||||
broker.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
if (connection != null) {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
broker.stop();
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void configureBroker(BrokerService broker) throws Exception {
|
|
||||||
PolicyMap policyMap = new PolicyMap();
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
policy.setPersistJMSRedelivered(true);
|
|
||||||
policyMap.setDefaultEntry(policy);
|
|
||||||
broker.setDestinationPolicy(policyMap);
|
|
||||||
setPersistenceAdapter(broker, persistenceAdapterChoice);
|
|
||||||
broker.addConnector("tcp://0.0.0.0:0");
|
|
||||||
}
|
|
||||||
|
|
||||||
@org.junit.Test
|
|
||||||
public void testValidateRedeliveryFlagAfterRestartNoTx() throws Exception {
|
|
||||||
|
|
||||||
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("failover:(" + broker.getTransportConnectors().get(0).getPublishableConnectString() + ")?jms.prefetchPolicy.all=0");
|
|
||||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
Destination destination = session.createQueue(queueName);
|
|
||||||
populateDestination(10, destination, connection);
|
|
||||||
|
|
||||||
MessageConsumer consumer = session.createConsumer(destination);
|
|
||||||
TextMessage msg = null;
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(20000);
|
|
||||||
LOG.info("not redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message", msg);
|
|
||||||
assertEquals("first delivery", 1, msg.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
assertEquals("not a redelivery", false, msg.getJMSRedelivered());
|
|
||||||
}
|
|
||||||
consumer.close();
|
|
||||||
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// make failover aware of the restarted auto assigned port
|
|
||||||
connection.getTransport().narrow(FailoverTransport.class).add(true, broker.getTransportConnectors().get(0).getPublishableConnectString());
|
|
||||||
|
|
||||||
consumer = session.createConsumer(destination);
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(4000);
|
|
||||||
LOG.info("redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message again", msg);
|
|
||||||
assertEquals("re delivery flag", true, msg.getJMSRedelivered());
|
|
||||||
assertEquals("redelivery count survives restart", 2, msg.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
msg.acknowledge();
|
|
||||||
}
|
|
||||||
|
|
||||||
// consume the rest that were not redeliveries
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(20000);
|
|
||||||
LOG.info("not redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message", msg);
|
|
||||||
assertEquals("not a redelivery", false, msg.getJMSRedelivered());
|
|
||||||
assertEquals("first delivery", 1, msg.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
msg.acknowledge();
|
|
||||||
}
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@org.junit.Test
|
|
||||||
public void testDurableSubRedeliveryFlagAfterRestartNotSupported() throws Exception {
|
|
||||||
|
|
||||||
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("failover:(" + broker.getTransportConnectors().get(0).getPublishableConnectString() + ")?jms.prefetchPolicy.all=0");
|
|
||||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
|
||||||
connection.setClientID("id");
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
ActiveMQTopic destination = new ActiveMQTopic(queueName);
|
|
||||||
|
|
||||||
TopicSubscriber durableSub = session.createDurableSubscriber(destination, "id");
|
|
||||||
|
|
||||||
populateDestination(10, destination, connection);
|
|
||||||
|
|
||||||
TextMessage msg = null;
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
msg = (TextMessage) durableSub.receive(20000);
|
|
||||||
LOG.info("not redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message", msg);
|
|
||||||
assertEquals("first delivery", 1, msg.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
assertEquals("not a redelivery", false, msg.getJMSRedelivered());
|
|
||||||
}
|
|
||||||
durableSub.close();
|
|
||||||
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// make failover aware of the restarted auto assigned port
|
|
||||||
connection.getTransport().narrow(FailoverTransport.class).add(true, broker.getTransportConnectors().get(0).getPublishableConnectString());
|
|
||||||
|
|
||||||
durableSub = session.createDurableSubscriber(destination, "id");
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
msg = (TextMessage) durableSub.receive(4000);
|
|
||||||
LOG.info("redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message again", msg);
|
|
||||||
assertEquals("no reDelivery flag", false, msg.getJMSRedelivered());
|
|
||||||
msg.acknowledge();
|
|
||||||
}
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@org.junit.Test
|
|
||||||
public void testValidateRedeliveryFlagAfterRestart() throws Exception {
|
|
||||||
|
|
||||||
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("failover:(" + broker.getTransportConnectors().get(0).getPublishableConnectString() + ")?jms.prefetchPolicy.all=0");
|
|
||||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
|
||||||
Destination destination = session.createQueue(queueName);
|
|
||||||
populateDestination(10, destination, connection);
|
|
||||||
|
|
||||||
MessageConsumer consumer = session.createConsumer(destination);
|
|
||||||
TextMessage msg = null;
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(20000);
|
|
||||||
LOG.info("not redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message", msg);
|
|
||||||
assertEquals("first delivery", 1, msg.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
assertEquals("not a redelivery", false, msg.getJMSRedelivered());
|
|
||||||
}
|
|
||||||
session.rollback();
|
|
||||||
consumer.close();
|
|
||||||
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
// make failover aware of the restarted auto assigned port
|
|
||||||
connection.getTransport().narrow(FailoverTransport.class).add(true, broker.getTransportConnectors().get(0).getPublishableConnectString());
|
|
||||||
|
|
||||||
consumer = session.createConsumer(destination);
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(4000);
|
|
||||||
LOG.info("redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message again", msg);
|
|
||||||
assertEquals("redelivery count survives restart", 2, msg.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
assertEquals("re delivery flag", true, msg.getJMSRedelivered());
|
|
||||||
}
|
|
||||||
session.commit();
|
|
||||||
|
|
||||||
// consume the rest that were not redeliveries
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(20000);
|
|
||||||
LOG.info("not redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message", msg);
|
|
||||||
assertEquals("first delivery", 1, msg.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
assertEquals("not a redelivery", false, msg.getJMSRedelivered());
|
|
||||||
}
|
|
||||||
session.commit();
|
|
||||||
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@org.junit.Test
|
|
||||||
public void testValidateRedeliveryFlagAfterRecovery() throws Exception {
|
|
||||||
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getPublishableConnectString() + "?jms.prefetchPolicy.all=0");
|
|
||||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
|
||||||
Destination destination = session.createQueue(queueName);
|
|
||||||
populateDestination(1, destination, connection);
|
|
||||||
|
|
||||||
MessageConsumer consumer = session.createConsumer(destination);
|
|
||||||
TextMessage msg = (TextMessage) consumer.receive(5000);
|
|
||||||
LOG.info("got: " + msg);
|
|
||||||
assertNotNull("got the message", msg);
|
|
||||||
assertEquals("first delivery", 1, msg.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
assertEquals("not a redelivery", false, msg.getJMSRedelivered());
|
|
||||||
|
|
||||||
stopBrokerWithStoreFailure(broker, persistenceAdapterChoice);
|
|
||||||
|
|
||||||
broker = createRestartedBroker();
|
|
||||||
broker.start();
|
|
||||||
|
|
||||||
connection.close();
|
|
||||||
|
|
||||||
connectionFactory = new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getPublishableConnectString());
|
|
||||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
|
||||||
consumer = session.createConsumer(destination);
|
|
||||||
msg = (TextMessage) consumer.receive(10000);
|
|
||||||
assertNotNull("got the message again", msg);
|
|
||||||
assertEquals("redelivery count survives restart", 2, msg.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
assertEquals("re delivery flag", true, msg.getJMSRedelivered());
|
|
||||||
|
|
||||||
session.commit();
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void restartBroker() throws Exception {
|
|
||||||
broker.stop();
|
|
||||||
broker.waitUntilStopped();
|
|
||||||
broker = createRestartedBroker();
|
|
||||||
broker.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private BrokerService createRestartedBroker() throws Exception {
|
|
||||||
broker = new BrokerService();
|
|
||||||
configureBroker(broker);
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void populateDestination(final int nbMessages,
|
|
||||||
final Destination destination,
|
|
||||||
javax.jms.Connection connection) throws JMSException {
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageProducer producer = session.createProducer(destination);
|
|
||||||
for (int i = 1; i <= nbMessages; i++) {
|
|
||||||
producer.send(session.createTextMessage("<hello id='" + i + "'/>"));
|
|
||||||
}
|
|
||||||
producer.close();
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,468 +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.broker;
|
|
||||||
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
import javax.jms.DeliveryMode;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TextMessage;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.TestSupport;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.broker.scheduler.JobSchedulerStore;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.command.ProducerId;
|
|
||||||
import org.apache.activemq.store.MessageStore;
|
|
||||||
import org.apache.activemq.store.PersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.ProxyMessageStore;
|
|
||||||
import org.apache.activemq.store.ProxyTopicMessageStore;
|
|
||||||
import org.apache.activemq.store.TopicMessageStore;
|
|
||||||
import org.apache.activemq.store.TransactionStore;
|
|
||||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
|
||||||
import org.apache.activemq.transport.tcp.TcpTransport;
|
|
||||||
import org.apache.activemq.usage.SystemUsage;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class RedeliveryRestartWithExceptionTest extends TestSupport {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(RedeliveryRestartWithExceptionTest.class);
|
|
||||||
ActiveMQConnection connection;
|
|
||||||
BrokerService broker = null;
|
|
||||||
String queueName = "redeliveryRestartQ";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
broker = new BrokerService();
|
|
||||||
configureBroker(broker, true);
|
|
||||||
broker.setDeleteAllMessagesOnStartup(true);
|
|
||||||
broker.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
if (connection != null) {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
broker.stop();
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void configureBroker(BrokerService broker, boolean throwExceptionOnUpdate) throws Exception {
|
|
||||||
PolicyMap policyMap = new PolicyMap();
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
policy.setPersistJMSRedelivered(true);
|
|
||||||
policyMap.setDefaultEntry(policy);
|
|
||||||
broker.setDestinationPolicy(policyMap);
|
|
||||||
broker.setPersistenceAdapter(new KahaDBWithUpdateExceptionPersistenceAdapter(throwExceptionOnUpdate));
|
|
||||||
broker.addConnector("tcp://0.0.0.0:0");
|
|
||||||
}
|
|
||||||
|
|
||||||
@org.junit.Test
|
|
||||||
public void testValidateRedeliveryFlagAfterRestart() throws Exception {
|
|
||||||
|
|
||||||
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getPublishableConnectString() + "?jms.prefetchPolicy.all=0");
|
|
||||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
Destination destination = session.createQueue(queueName);
|
|
||||||
populateDestination(10, destination, connection, true);
|
|
||||||
TextMessage msg = null;
|
|
||||||
MessageConsumer consumer = session.createConsumer(destination);
|
|
||||||
Exception expectedException = null;
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(5000);
|
|
||||||
LOG.info("not redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message", msg);
|
|
||||||
assertTrue("Should not receive the 5th message", i < 4);
|
|
||||||
//The first 4 messages will be ok but the 5th one should hit an exception in updateMessage and should not be delivered
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
//Expecting an exception and disconnect on the 5th message
|
|
||||||
LOG.info("Got expected:", e);
|
|
||||||
expectedException = e;
|
|
||||||
}
|
|
||||||
assertNotNull("Expecting an exception when updateMessage fails", expectedException);
|
|
||||||
|
|
||||||
consumer.close();
|
|
||||||
connection.close();
|
|
||||||
|
|
||||||
restartBroker();
|
|
||||||
|
|
||||||
connectionFactory = new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getPublishableConnectString() + "?jms.prefetchPolicy.all=0");
|
|
||||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
destination = session.createQueue(queueName);
|
|
||||||
consumer = session.createConsumer(destination);
|
|
||||||
|
|
||||||
// consume the messages that were previously delivered
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(4000);
|
|
||||||
LOG.info("redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message again", msg);
|
|
||||||
assertEquals("re delivery flag", true, msg.getJMSRedelivered());
|
|
||||||
assertTrue("redelivery count survives restart", msg.getLongProperty("JMSXDeliveryCount") > 1);
|
|
||||||
msg.acknowledge();
|
|
||||||
}
|
|
||||||
|
|
||||||
// consume the rest that were not redeliveries
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(4000);
|
|
||||||
LOG.info("not redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message", msg);
|
|
||||||
assertEquals("not a redelivery", false, msg.getJMSRedelivered());
|
|
||||||
assertEquals("first delivery", 1, msg.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
msg.acknowledge();
|
|
||||||
}
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@org.junit.Test
|
|
||||||
public void testValidateRedeliveryFlagAfterTransientFailureConnectionDrop() throws Exception {
|
|
||||||
|
|
||||||
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getPublishableConnectString() + "?jms.prefetchPolicy.all=0");
|
|
||||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
Destination destination = session.createQueue(queueName);
|
|
||||||
populateDestination(10, destination, connection, true);
|
|
||||||
TextMessage msg = null;
|
|
||||||
MessageConsumer consumer = session.createConsumer(destination);
|
|
||||||
Exception expectedException = null;
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(5000);
|
|
||||||
LOG.info("not redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message", msg);
|
|
||||||
assertTrue("Should not receive the 5th message", i < 4);
|
|
||||||
//The first 4 messages will be ok but the 5th one should hit an exception in updateMessage and should not be delivered
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
//Expecting an exception and disconnect on the 5th message
|
|
||||||
LOG.info("Got expected:", e);
|
|
||||||
expectedException = e;
|
|
||||||
}
|
|
||||||
assertNotNull("Expecting an exception when updateMessage fails", expectedException);
|
|
||||||
|
|
||||||
consumer.close();
|
|
||||||
connection.close();
|
|
||||||
|
|
||||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
destination = session.createQueue(queueName);
|
|
||||||
consumer = session.createConsumer(destination);
|
|
||||||
|
|
||||||
// consume the messages that were previously delivered
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(4000);
|
|
||||||
LOG.info("redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message again", msg);
|
|
||||||
assertEquals("re delivery flag on:" + i, true, msg.getJMSRedelivered());
|
|
||||||
assertTrue("redelivery count survives reconnect for:" + i, msg.getLongProperty("JMSXDeliveryCount") > 1);
|
|
||||||
msg.acknowledge();
|
|
||||||
}
|
|
||||||
|
|
||||||
// consume the rest that were not redeliveries
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(4000);
|
|
||||||
LOG.info("not redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message", msg);
|
|
||||||
assertEquals("not a redelivery", false, msg.getJMSRedelivered());
|
|
||||||
assertEquals("first delivery", 1, msg.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
msg.acknowledge();
|
|
||||||
}
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@org.junit.Test
|
|
||||||
public void testValidateRedeliveryFlagOnNonPersistentAfterTransientFailureConnectionDrop() throws Exception {
|
|
||||||
|
|
||||||
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getPublishableConnectString() + "?jms.prefetchPolicy.all=0");
|
|
||||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
Destination destination = session.createQueue(queueName);
|
|
||||||
populateDestination(10, destination, connection, false);
|
|
||||||
TextMessage msg = null;
|
|
||||||
MessageConsumer consumer = session.createConsumer(destination);
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(5000);
|
|
||||||
assertNotNull("got the message", msg);
|
|
||||||
assertFalse("not redelivered", msg.getJMSRedelivered());
|
|
||||||
}
|
|
||||||
|
|
||||||
connection.getTransport().narrow(TcpTransport.class).getTransportListener().onException(new IOException("Die"));
|
|
||||||
|
|
||||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
destination = session.createQueue(queueName);
|
|
||||||
consumer = session.createConsumer(destination);
|
|
||||||
|
|
||||||
// consume the messages that were previously delivered
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(4000);
|
|
||||||
LOG.info("redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message again", msg);
|
|
||||||
assertEquals("redelivery flag set on:" + i, true, msg.getJMSRedelivered());
|
|
||||||
assertTrue("redelivery count survives reconnect for:" + i, msg.getLongProperty("JMSXDeliveryCount") > 1);
|
|
||||||
msg.acknowledge();
|
|
||||||
}
|
|
||||||
|
|
||||||
// consume the rest that were not redeliveries
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
msg = (TextMessage) consumer.receive(4000);
|
|
||||||
LOG.info("not redelivered? got: " + msg);
|
|
||||||
assertNotNull("got the message", msg);
|
|
||||||
assertEquals("not a redelivery", false, msg.getJMSRedelivered());
|
|
||||||
assertEquals("first delivery", 1, msg.getLongProperty("JMSXDeliveryCount"));
|
|
||||||
msg.acknowledge();
|
|
||||||
}
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void restartBroker() throws Exception {
|
|
||||||
broker.stop();
|
|
||||||
broker.waitUntilStopped();
|
|
||||||
broker = createRestartedBroker();
|
|
||||||
broker.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private BrokerService createRestartedBroker() throws Exception {
|
|
||||||
broker = new BrokerService();
|
|
||||||
configureBroker(broker, false);
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void populateDestination(final int nbMessages,
|
|
||||||
final Destination destination,
|
|
||||||
javax.jms.Connection connection,
|
|
||||||
boolean persistent) throws JMSException {
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageProducer producer = session.createProducer(destination);
|
|
||||||
producer.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
|
|
||||||
for (int i = 1; i <= nbMessages; i++) {
|
|
||||||
producer.send(session.createTextMessage("<hello id='" + i + "'/>"));
|
|
||||||
}
|
|
||||||
producer.close();
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class KahaDBWithUpdateExceptionPersistenceAdapter implements PersistenceAdapter {
|
|
||||||
|
|
||||||
private KahaDBPersistenceAdapter kahaDB = new KahaDBPersistenceAdapter();
|
|
||||||
private boolean throwExceptionOnUpdate;
|
|
||||||
|
|
||||||
public KahaDBWithUpdateExceptionPersistenceAdapter(boolean throwExceptionOnUpdate) {
|
|
||||||
this.throwExceptionOnUpdate = throwExceptionOnUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start() throws Exception {
|
|
||||||
kahaDB.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stop() throws Exception {
|
|
||||||
kahaDB.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<ActiveMQDestination> getDestinations() {
|
|
||||||
return kahaDB.getDestinations();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MessageStore createQueueMessageStore(ActiveMQQueue destination) throws IOException {
|
|
||||||
MessageStore proxyMessageStoreWithException = new ProxyMessageStoreWithUpdateException(kahaDB.createQueueMessageStore(destination), throwExceptionOnUpdate);
|
|
||||||
return proxyMessageStoreWithException;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TopicMessageStore createTopicMessageStore(ActiveMQTopic destination) throws IOException {
|
|
||||||
TopicMessageStore proxyMessageStoreWithException = new ProxyTopicMessageStoreWithUpdateException(kahaDB.createTopicMessageStore(destination), throwExceptionOnUpdate);
|
|
||||||
return proxyMessageStoreWithException;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JobSchedulerStore createJobSchedulerStore() throws IOException, UnsupportedOperationException {
|
|
||||||
return kahaDB.createJobSchedulerStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeQueueMessageStore(ActiveMQQueue destination) {
|
|
||||||
kahaDB.removeQueueMessageStore(destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeTopicMessageStore(ActiveMQTopic destination) {
|
|
||||||
kahaDB.removeTopicMessageStore(destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TransactionStore createTransactionStore() throws IOException {
|
|
||||||
return kahaDB.createTransactionStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beginTransaction(ConnectionContext context) throws IOException {
|
|
||||||
kahaDB.beginTransaction(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void commitTransaction(ConnectionContext context) throws IOException {
|
|
||||||
kahaDB.commitTransaction(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void rollbackTransaction(ConnectionContext context) throws IOException {
|
|
||||||
kahaDB.rollbackTransaction(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getLastMessageBrokerSequenceId() throws IOException {
|
|
||||||
return kahaDB.getLastMessageBrokerSequenceId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteAllMessages() throws IOException {
|
|
||||||
kahaDB.deleteAllMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUsageManager(SystemUsage usageManager) {
|
|
||||||
kahaDB.setUsageManager(usageManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBrokerName(String brokerName) {
|
|
||||||
kahaDB.setBrokerName(brokerName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDirectory(File dir) {
|
|
||||||
kahaDB.setDirectory(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public File getDirectory() {
|
|
||||||
return kahaDB.getDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkpoint(boolean sync) throws IOException {
|
|
||||||
kahaDB.checkpoint(sync);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long size() {
|
|
||||||
return kahaDB.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getLastProducerSequenceId(ProducerId id) throws IOException {
|
|
||||||
return kahaDB.getLastProducerSequenceId(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void allowIOResumption() {
|
|
||||||
kahaDB.allowIOResumption();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ProxyMessageStoreWithUpdateException extends ProxyMessageStore {
|
|
||||||
|
|
||||||
private boolean throwExceptionOnUpdate;
|
|
||||||
private int numBeforeException = 4;
|
|
||||||
|
|
||||||
public ProxyMessageStoreWithUpdateException(MessageStore delegate, boolean throwExceptionOnUpdate) {
|
|
||||||
super(delegate);
|
|
||||||
this.throwExceptionOnUpdate = throwExceptionOnUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateMessage(Message message) throws IOException {
|
|
||||||
if (throwExceptionOnUpdate) {
|
|
||||||
if (numBeforeException > 0) {
|
|
||||||
numBeforeException--;
|
|
||||||
super.updateMessage(message);
|
|
||||||
} else {
|
|
||||||
// lets only do it once so we can validate transient store failure
|
|
||||||
throwExceptionOnUpdate = false;
|
|
||||||
|
|
||||||
//A message that has never been delivered will hit this exception
|
|
||||||
throw new IOException("Hit our simulated exception writing the update to disk");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
super.updateMessage(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ProxyTopicMessageStoreWithUpdateException extends ProxyTopicMessageStore {
|
|
||||||
|
|
||||||
private boolean throwExceptionOnUpdate;
|
|
||||||
private int numBeforeException = 4;
|
|
||||||
|
|
||||||
public ProxyTopicMessageStoreWithUpdateException(TopicMessageStore delegate, boolean throwExceptionOnUpdate) {
|
|
||||||
super(delegate);
|
|
||||||
this.throwExceptionOnUpdate = throwExceptionOnUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateMessage(Message message) throws IOException {
|
|
||||||
if (throwExceptionOnUpdate) {
|
|
||||||
if (numBeforeException > 0) {
|
|
||||||
numBeforeException--;
|
|
||||||
super.updateMessage(message);
|
|
||||||
} else {
|
|
||||||
//A message that has never been delivered will hit this exception
|
|
||||||
throw new IOException("Hit our simulated exception writing the update to disk");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
super.updateMessage(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,107 +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.broker;
|
|
||||||
|
|
||||||
import javax.jms.Message;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.activemq.spring.SpringConsumer;
|
|
||||||
import org.apache.activemq.spring.SpringProducer;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.context.support.AbstractApplicationContext;
|
|
||||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
|
||||||
|
|
||||||
public class SpringTest extends TestCase {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SpringTest.class);
|
|
||||||
|
|
||||||
protected AbstractApplicationContext context;
|
|
||||||
protected SpringConsumer consumer;
|
|
||||||
protected SpringProducer producer;
|
|
||||||
|
|
||||||
public void testSenderWithSpringXml() throws Exception {
|
|
||||||
assertSenderConfig("org/apache/activemq/broker/spring.xml");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* assert method that is used by all the test method to send and receive messages
|
|
||||||
* based on each spring configuration.
|
|
||||||
*
|
|
||||||
* @param config
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
protected void assertSenderConfig(String config) throws Exception {
|
|
||||||
context = new ClassPathXmlApplicationContext(config);
|
|
||||||
|
|
||||||
consumer = (SpringConsumer) context.getBean("consumer");
|
|
||||||
assertTrue("Found a valid consumer", consumer != null);
|
|
||||||
|
|
||||||
consumer.start();
|
|
||||||
|
|
||||||
producer = (SpringProducer) context.getBean("producer");
|
|
||||||
assertTrue("Found a valid producer", producer != null);
|
|
||||||
|
|
||||||
consumer.flushMessages();
|
|
||||||
producer.start();
|
|
||||||
|
|
||||||
// lets sleep a little to give the JMS time to dispatch stuff
|
|
||||||
consumer.waitForMessagesToArrive(producer.getMessageCount());
|
|
||||||
|
|
||||||
// now lets check that the consumer has received some messages
|
|
||||||
List<Message> messages = consumer.flushMessages();
|
|
||||||
LOG.info("Consumer has received messages....");
|
|
||||||
for (Message message : messages) {
|
|
||||||
LOG.info("Received: " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals("Message count", producer.getMessageCount(), messages.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean up method.
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
if (consumer != null) {
|
|
||||||
consumer.stop();
|
|
||||||
}
|
|
||||||
if (producer != null) {
|
|
||||||
producer.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context != null) {
|
|
||||||
context.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
if (System.getProperty("basedir") == null) {
|
|
||||||
File file = new File(".");
|
|
||||||
System.setProperty("basedir", file.getAbsolutePath());
|
|
||||||
}
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,163 +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.broker;
|
|
||||||
|
|
||||||
import org.apache.activemq.util.ThreadTracker;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
|
||||||
|
|
||||||
@RunWith(BlockJUnit4ClassRunner.class)
|
|
||||||
public class TopicSubscriptionTest extends QueueSubscriptionTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
durable = true;
|
|
||||||
topic = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
ThreadTracker.result();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testManyProducersManyConsumers() throws Exception {
|
|
||||||
consumerCount = 40;
|
|
||||||
producerCount = 20;
|
|
||||||
messageCount = 100;
|
|
||||||
messageSize = 1;
|
|
||||||
prefetchCount = 10;
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * producerCount * consumerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersLargeMessagesOnePrefetch() throws Exception {
|
|
||||||
consumerCount = 2;
|
|
||||||
producerCount = 1;
|
|
||||||
messageCount = 10;
|
|
||||||
messageSize = 1024 * 1024 * 1; // 1 MB
|
|
||||||
prefetchCount = 1;
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * consumerCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersSmallMessagesOnePrefetch() throws Exception {
|
|
||||||
consumerCount = 2;
|
|
||||||
producerCount = 1;
|
|
||||||
prefetchCount = 1;
|
|
||||||
messageSize = 1024;
|
|
||||||
messageCount = 1000;
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * consumerCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersSmallMessagesLargePrefetch() throws Exception {
|
|
||||||
consumerCount = 2;
|
|
||||||
producerCount = 1;
|
|
||||||
messageCount = 1000;
|
|
||||||
messageSize = 1024;
|
|
||||||
prefetchCount = messageCount * 2;
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * consumerCount * producerCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersLargeMessagesLargePrefetch() throws Exception {
|
|
||||||
consumerCount = 2;
|
|
||||||
producerCount = 1;
|
|
||||||
messageCount = 10;
|
|
||||||
messageSize = 1024 * 1024 * 1; // 1 MB
|
|
||||||
prefetchCount = messageCount * 2;
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * consumerCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerManyConsumersFewMessages() throws Exception {
|
|
||||||
consumerCount = 50;
|
|
||||||
producerCount = 1;
|
|
||||||
messageCount = 10;
|
|
||||||
messageSize = 1; // 1 byte
|
|
||||||
prefetchCount = 10;
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * consumerCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerManyConsumersManyMessages() throws Exception {
|
|
||||||
consumerCount = 50;
|
|
||||||
producerCount = 1;
|
|
||||||
messageCount = 100;
|
|
||||||
messageSize = 1; // 1 byte
|
|
||||||
prefetchCount = 10;
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * consumerCount * producerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testManyProducersOneConsumer() throws Exception {
|
|
||||||
consumerCount = 1;
|
|
||||||
producerCount = 20;
|
|
||||||
messageCount = 100;
|
|
||||||
messageSize = 1; // 1 byte
|
|
||||||
prefetchCount = 10;
|
|
||||||
|
|
||||||
doMultipleClientsTest();
|
|
||||||
|
|
||||||
assertTotalMessagesReceived(messageCount * producerCount * consumerCount);
|
|
||||||
assertDestinationMemoryUsageGoesToZero();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,329 +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.broker.advisory;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
import org.apache.activemq.advisory.AdvisorySupport;
|
|
||||||
import org.apache.activemq.broker.BrokerTestSupport;
|
|
||||||
import org.apache.activemq.broker.StubConnection;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ConnectionInfo;
|
|
||||||
import org.apache.activemq.command.ConsumerInfo;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.command.ProducerInfo;
|
|
||||||
import org.apache.activemq.command.RemoveInfo;
|
|
||||||
import org.apache.activemq.command.SessionInfo;
|
|
||||||
|
|
||||||
public class AdvisoryBrokerTest extends BrokerTestSupport {
|
|
||||||
|
|
||||||
public void testConnectionAdvisories() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination destination = AdvisorySupport.getConnectionAdvisoryTopic();
|
|
||||||
|
|
||||||
// Setup a first connection
|
|
||||||
StubConnection connection1 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo1 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo1 = createSessionInfo(connectionInfo1);
|
|
||||||
ConsumerInfo consumerInfo1 = createConsumerInfo(sessionInfo1, destination);
|
|
||||||
consumerInfo1.setPrefetchSize(100);
|
|
||||||
|
|
||||||
connection1.send(connectionInfo1);
|
|
||||||
connection1.send(sessionInfo1);
|
|
||||||
connection1.send(consumerInfo1);
|
|
||||||
|
|
||||||
// We should get an advisory of our own connection.
|
|
||||||
Message m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
assertEquals(((ConnectionInfo) m1.getDataStructure()).getConnectionId(), connectionInfo1.getConnectionId());
|
|
||||||
|
|
||||||
// Setup a second connection
|
|
||||||
StubConnection connection2 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo2 = createConnectionInfo();
|
|
||||||
connection2.send(connectionInfo2);
|
|
||||||
|
|
||||||
// We should get an advisory of the second connection.
|
|
||||||
m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
assertEquals(((ConnectionInfo) m1.getDataStructure()).getConnectionId(), connectionInfo2.getConnectionId());
|
|
||||||
|
|
||||||
// Close the second connection.
|
|
||||||
connection2.send(closeConnectionInfo(connectionInfo2));
|
|
||||||
connection2.stop();
|
|
||||||
|
|
||||||
// We should get an advisory of the second connection closing
|
|
||||||
m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
RemoveInfo r = (RemoveInfo) m1.getDataStructure();
|
|
||||||
assertEquals(r.getObjectId(), connectionInfo2.getConnectionId());
|
|
||||||
|
|
||||||
assertNoMessagesLeft(connection1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testConsumerAdvisories() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination queue = new ActiveMQQueue("test");
|
|
||||||
ActiveMQDestination destination = AdvisorySupport.getConsumerAdvisoryTopic(queue);
|
|
||||||
|
|
||||||
// Setup a first connection
|
|
||||||
StubConnection connection1 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo1 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo1 = createSessionInfo(connectionInfo1);
|
|
||||||
ConsumerInfo consumerInfo1 = createConsumerInfo(sessionInfo1, destination);
|
|
||||||
consumerInfo1.setPrefetchSize(100);
|
|
||||||
|
|
||||||
connection1.send(connectionInfo1);
|
|
||||||
connection1.send(sessionInfo1);
|
|
||||||
connection1.send(consumerInfo1);
|
|
||||||
|
|
||||||
// We should not see and advisory for the advisory consumer.
|
|
||||||
assertNoMessagesLeft(connection1);
|
|
||||||
|
|
||||||
// Setup a second consumer.
|
|
||||||
StubConnection connection2 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo2 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo2 = createSessionInfo(connectionInfo2);
|
|
||||||
ConsumerInfo consumerInfo2 = createConsumerInfo(sessionInfo2, queue);
|
|
||||||
consumerInfo1.setPrefetchSize(100);
|
|
||||||
|
|
||||||
connection2.send(connectionInfo2);
|
|
||||||
connection2.send(sessionInfo2);
|
|
||||||
connection2.send(consumerInfo2);
|
|
||||||
|
|
||||||
// We should get an advisory of the new consumer.
|
|
||||||
Message m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
assertEquals(((ConsumerInfo) m1.getDataStructure()).getConsumerId(), consumerInfo2.getConsumerId());
|
|
||||||
|
|
||||||
// Close the second connection.
|
|
||||||
connection2.request(closeConnectionInfo(connectionInfo2));
|
|
||||||
connection2.stop();
|
|
||||||
|
|
||||||
// We should get an advisory of the consumer closing
|
|
||||||
m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
RemoveInfo r = (RemoveInfo) m1.getDataStructure();
|
|
||||||
assertEquals(r.getObjectId(), consumerInfo2.getConsumerId());
|
|
||||||
|
|
||||||
assertNoMessagesLeft(connection2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testConsumerAdvisoriesReplayed() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination queue = new ActiveMQQueue("test");
|
|
||||||
ActiveMQDestination destination = AdvisorySupport.getConsumerAdvisoryTopic(queue);
|
|
||||||
|
|
||||||
// Setup a first connection
|
|
||||||
StubConnection connection1 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo1 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo1 = createSessionInfo(connectionInfo1);
|
|
||||||
|
|
||||||
connection1.send(connectionInfo1);
|
|
||||||
connection1.send(sessionInfo1);
|
|
||||||
|
|
||||||
// Setup a second consumer.
|
|
||||||
StubConnection connection2 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo2 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo2 = createSessionInfo(connectionInfo2);
|
|
||||||
ConsumerInfo consumerInfo2 = createConsumerInfo(sessionInfo2, queue);
|
|
||||||
consumerInfo2.setPrefetchSize(100);
|
|
||||||
connection2.send(connectionInfo2);
|
|
||||||
connection2.send(sessionInfo2);
|
|
||||||
connection2.send(consumerInfo2);
|
|
||||||
|
|
||||||
// We should get an advisory of the previous consumer.
|
|
||||||
ConsumerInfo consumerInfo1 = createConsumerInfo(sessionInfo1, destination);
|
|
||||||
consumerInfo1.setPrefetchSize(100);
|
|
||||||
connection1.send(consumerInfo1);
|
|
||||||
|
|
||||||
Message m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
assertEquals(((ConsumerInfo) m1.getDataStructure()).getConsumerId(), consumerInfo2.getConsumerId());
|
|
||||||
|
|
||||||
// Close the second connection.
|
|
||||||
connection2.request(closeConnectionInfo(connectionInfo2));
|
|
||||||
connection2.stop();
|
|
||||||
|
|
||||||
// We should get an advisory of the consumer closing
|
|
||||||
m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
RemoveInfo r = (RemoveInfo) m1.getDataStructure();
|
|
||||||
assertEquals(r.getObjectId(), consumerInfo2.getConsumerId());
|
|
||||||
|
|
||||||
assertNoMessagesLeft(connection2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testProducerAdvisories() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination queue = new ActiveMQQueue("test");
|
|
||||||
ActiveMQDestination destination = AdvisorySupport.getProducerAdvisoryTopic(queue);
|
|
||||||
|
|
||||||
// Setup a first connection
|
|
||||||
StubConnection connection1 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo1 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo1 = createSessionInfo(connectionInfo1);
|
|
||||||
ConsumerInfo consumerInfo1 = createConsumerInfo(sessionInfo1, destination);
|
|
||||||
consumerInfo1.setPrefetchSize(100);
|
|
||||||
|
|
||||||
connection1.send(connectionInfo1);
|
|
||||||
connection1.send(sessionInfo1);
|
|
||||||
connection1.send(consumerInfo1);
|
|
||||||
|
|
||||||
assertNoMessagesLeft(connection1);
|
|
||||||
|
|
||||||
// Setup a producer.
|
|
||||||
StubConnection connection2 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo2 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo2 = createSessionInfo(connectionInfo2);
|
|
||||||
ProducerInfo producerInfo2 = createProducerInfo(sessionInfo2);
|
|
||||||
producerInfo2.setDestination(queue);
|
|
||||||
|
|
||||||
connection2.send(connectionInfo2);
|
|
||||||
connection2.send(sessionInfo2);
|
|
||||||
connection2.send(producerInfo2);
|
|
||||||
|
|
||||||
// We should get an advisory of the new producer.
|
|
||||||
Message m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
assertEquals(((ProducerInfo) m1.getDataStructure()).getProducerId(), producerInfo2.getProducerId());
|
|
||||||
|
|
||||||
// Close the second connection.
|
|
||||||
connection2.request(closeConnectionInfo(connectionInfo2));
|
|
||||||
connection2.stop();
|
|
||||||
|
|
||||||
// We should get an advisory of the producer closing
|
|
||||||
m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
RemoveInfo r = (RemoveInfo) m1.getDataStructure();
|
|
||||||
assertEquals(r.getObjectId(), producerInfo2.getProducerId());
|
|
||||||
|
|
||||||
assertNoMessagesLeft(connection2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testProducerAdvisoriesReplayed() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination queue = new ActiveMQQueue("test");
|
|
||||||
ActiveMQDestination destination = AdvisorySupport.getProducerAdvisoryTopic(queue);
|
|
||||||
|
|
||||||
// Setup a first connection
|
|
||||||
StubConnection connection1 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo1 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo1 = createSessionInfo(connectionInfo1);
|
|
||||||
|
|
||||||
connection1.send(connectionInfo1);
|
|
||||||
connection1.send(sessionInfo1);
|
|
||||||
|
|
||||||
// Setup a producer.
|
|
||||||
StubConnection connection2 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo2 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo2 = createSessionInfo(connectionInfo2);
|
|
||||||
ProducerInfo producerInfo2 = createProducerInfo(sessionInfo2);
|
|
||||||
producerInfo2.setDestination(queue);
|
|
||||||
|
|
||||||
connection2.send(connectionInfo2);
|
|
||||||
connection2.send(sessionInfo2);
|
|
||||||
connection2.send(producerInfo2);
|
|
||||||
|
|
||||||
// Create the advisory consumer.. it should see the previous producer
|
|
||||||
ConsumerInfo consumerInfo1 = createConsumerInfo(sessionInfo1, destination);
|
|
||||||
consumerInfo1.setPrefetchSize(100);
|
|
||||||
connection1.send(consumerInfo1);
|
|
||||||
|
|
||||||
Message m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
assertEquals(((ProducerInfo) m1.getDataStructure()).getProducerId(), producerInfo2.getProducerId());
|
|
||||||
|
|
||||||
// Close the second connection.
|
|
||||||
connection2.request(closeConnectionInfo(connectionInfo2));
|
|
||||||
connection2.stop();
|
|
||||||
|
|
||||||
// We should get an advisory of the producer closing
|
|
||||||
m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
RemoveInfo r = (RemoveInfo) m1.getDataStructure();
|
|
||||||
assertEquals(r.getObjectId(), producerInfo2.getProducerId());
|
|
||||||
|
|
||||||
assertNoMessagesLeft(connection2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testProducerAdvisoriesReplayedOnlyTargetNewConsumer() throws Exception {
|
|
||||||
|
|
||||||
ActiveMQDestination queue = new ActiveMQQueue("test");
|
|
||||||
ActiveMQDestination destination = AdvisorySupport.getProducerAdvisoryTopic(queue);
|
|
||||||
|
|
||||||
// Setup a first connection
|
|
||||||
StubConnection connection1 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo1 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo1 = createSessionInfo(connectionInfo1);
|
|
||||||
connection1.send(connectionInfo1);
|
|
||||||
connection1.send(sessionInfo1);
|
|
||||||
// Create the first consumer..
|
|
||||||
ConsumerInfo consumerInfo1 = createConsumerInfo(sessionInfo1, destination);
|
|
||||||
consumerInfo1.setPrefetchSize(100);
|
|
||||||
connection1.send(consumerInfo1);
|
|
||||||
|
|
||||||
// Setup a producer.
|
|
||||||
StubConnection connection2 = createConnection();
|
|
||||||
ConnectionInfo connectionInfo2 = createConnectionInfo();
|
|
||||||
SessionInfo sessionInfo2 = createSessionInfo(connectionInfo2);
|
|
||||||
ProducerInfo producerInfo2 = createProducerInfo(sessionInfo2);
|
|
||||||
producerInfo2.setDestination(queue);
|
|
||||||
connection2.send(connectionInfo2);
|
|
||||||
connection2.send(sessionInfo2);
|
|
||||||
connection2.send(producerInfo2);
|
|
||||||
|
|
||||||
Message m1 = receiveMessage(connection1);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
assertEquals(((ProducerInfo) m1.getDataStructure()).getProducerId(), producerInfo2.getProducerId());
|
|
||||||
|
|
||||||
// Create the 2nd consumer..
|
|
||||||
ConsumerInfo consumerInfo2 = createConsumerInfo(sessionInfo2, destination);
|
|
||||||
consumerInfo2.setPrefetchSize(100);
|
|
||||||
connection2.send(consumerInfo2);
|
|
||||||
|
|
||||||
// The second consumer should se a replay
|
|
||||||
m1 = receiveMessage(connection2);
|
|
||||||
assertNotNull(m1);
|
|
||||||
assertNotNull(m1.getDataStructure());
|
|
||||||
assertEquals(((ProducerInfo) m1.getDataStructure()).getProducerId(), producerInfo2.getProducerId());
|
|
||||||
|
|
||||||
// But the first consumer should not see the replay.
|
|
||||||
assertNoMessagesLeft(connection1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(AdvisoryBrokerTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(suite());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,48 +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.broker.advisory;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerFactory;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
|
|
||||||
public class AdvisoryDuplexNetworkBridgeTest extends AdvisoryNetworkBridgeTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void createBroker1() throws Exception {
|
|
||||||
broker1 = new BrokerService();
|
|
||||||
broker1.setBrokerName("broker1");
|
|
||||||
broker1.addConnector("tcp://localhost:61617");
|
|
||||||
broker1.setUseJmx(false);
|
|
||||||
broker1.setPersistent(false);
|
|
||||||
broker1.start();
|
|
||||||
broker1.waitUntilStarted();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void createBroker2() throws Exception {
|
|
||||||
broker2 = BrokerFactory.createBroker(new URI("xbean:org/apache/activemq/network/duplexLocalBroker.xml"));
|
|
||||||
broker2.start();
|
|
||||||
broker2.waitUntilStarted();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void assertCreatedByDuplex(boolean createdByDuplex) {
|
|
||||||
assertTrue(createdByDuplex);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,88 +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.broker.advisory;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.management.MBeanServerConnection;
|
|
||||||
import javax.management.MBeanServerInvocationHandler;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
import javax.management.remote.JMXConnector;
|
|
||||||
import javax.management.remote.JMXConnectorFactory;
|
|
||||||
import javax.management.remote.JMXServiceURL;
|
|
||||||
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.jmx.BrokerViewMBean;
|
|
||||||
import org.apache.activemq.broker.jmx.ManagementContext;
|
|
||||||
import org.apache.activemq.command.ActiveMQMessage;
|
|
||||||
import org.apache.activemq.command.DestinationInfo;
|
|
||||||
|
|
||||||
public class AdvisoryJmxTest extends EmbeddedBrokerTestSupport {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService answer = new BrokerService();
|
|
||||||
answer.setPersistent(isPersistent());
|
|
||||||
answer.addConnector(bindAddress);
|
|
||||||
ManagementContext context = new ManagementContext();
|
|
||||||
context.setConnectorPort(1199);
|
|
||||||
answer.setManagementContext(context);
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCreateDeleteDestinations() throws Exception {
|
|
||||||
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1199/jmxrmi");
|
|
||||||
JMXConnector connector = JMXConnectorFactory.connect(url, null);
|
|
||||||
connector.connect();
|
|
||||||
MBeanServerConnection connection = connector.getMBeanServerConnection();
|
|
||||||
ObjectName name = new ObjectName("org.apache.activemq:type=Broker,brokerName=localhost");
|
|
||||||
BrokerViewMBean brokerMbean = MBeanServerInvocationHandler.newProxyInstance(connection, name, BrokerViewMBean.class, true);
|
|
||||||
Connection conn = createConnection();
|
|
||||||
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageConsumer consumer = sess.createConsumer(sess.createTopic("ActiveMQ.Advisory.Queue"));
|
|
||||||
conn.start();
|
|
||||||
Destination dest = sess.createQueue("test");
|
|
||||||
|
|
||||||
brokerMbean.addQueue("test");
|
|
||||||
|
|
||||||
ActiveMQMessage msg = (ActiveMQMessage) consumer.receive(1000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
assertTrue(msg.getDataStructure() instanceof DestinationInfo);
|
|
||||||
assertEquals(((DestinationInfo) msg.getDataStructure()).getDestination(), dest);
|
|
||||||
assertEquals(((DestinationInfo) msg.getDataStructure()).getOperationType(), 0);
|
|
||||||
|
|
||||||
brokerMbean.removeQueue("test");
|
|
||||||
|
|
||||||
msg = (ActiveMQMessage) consumer.receive(1000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
assertTrue(msg.getDataStructure() instanceof DestinationInfo);
|
|
||||||
assertEquals(((DestinationInfo) msg.getDataStructure()).getDestination(), dest);
|
|
||||||
assertEquals(((DestinationInfo) msg.getDataStructure()).getOperationType(), 1);
|
|
||||||
|
|
||||||
brokerMbean.addQueue("test");
|
|
||||||
msg = (ActiveMQMessage) consumer.receive(1000);
|
|
||||||
assertNotNull(msg);
|
|
||||||
assertTrue(msg.getDataStructure() instanceof DestinationInfo);
|
|
||||||
assertEquals(((DestinationInfo) msg.getDataStructure()).getDestination(), dest);
|
|
||||||
assertEquals(((DestinationInfo) msg.getDataStructure()).getOperationType(), 0);
|
|
||||||
assertEquals(((DestinationInfo) msg.getDataStructure()).getOperationType(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,127 +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.broker.advisory;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.advisory.AdvisorySupport;
|
|
||||||
import org.apache.activemq.broker.BrokerFactory;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.command.ActiveMQMessage;
|
|
||||||
import org.apache.activemq.command.BrokerInfo;
|
|
||||||
|
|
||||||
public class AdvisoryNetworkBridgeTest extends TestCase {
|
|
||||||
|
|
||||||
BrokerService broker1;
|
|
||||||
BrokerService broker2;
|
|
||||||
|
|
||||||
public void testAdvisory() throws Exception {
|
|
||||||
createBroker1();
|
|
||||||
|
|
||||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://broker1");
|
|
||||||
Connection conn = factory.createConnection();
|
|
||||||
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
conn.start();
|
|
||||||
MessageConsumer consumer = sess.createConsumer(AdvisorySupport.getNetworkBridgeAdvisoryTopic());
|
|
||||||
|
|
||||||
Thread.sleep(1000);
|
|
||||||
|
|
||||||
createBroker2();
|
|
||||||
|
|
||||||
ActiveMQMessage advisory = (ActiveMQMessage) consumer.receive(2000);
|
|
||||||
assertNotNull(advisory);
|
|
||||||
assertTrue(advisory.getDataStructure() instanceof BrokerInfo);
|
|
||||||
assertTrue(advisory.getBooleanProperty("started"));
|
|
||||||
assertCreatedByDuplex(advisory.getBooleanProperty("createdByDuplex"));
|
|
||||||
|
|
||||||
broker2.stop();
|
|
||||||
broker2.waitUntilStopped();
|
|
||||||
|
|
||||||
advisory = (ActiveMQMessage) consumer.receive(2000);
|
|
||||||
assertNotNull(advisory);
|
|
||||||
assertTrue(advisory.getDataStructure() instanceof BrokerInfo);
|
|
||||||
assertFalse(advisory.getBooleanProperty("started"));
|
|
||||||
|
|
||||||
conn.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAddConsumerLater() throws Exception {
|
|
||||||
createBroker1();
|
|
||||||
|
|
||||||
createBroker2();
|
|
||||||
|
|
||||||
Thread.sleep(1000);
|
|
||||||
|
|
||||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://broker1");
|
|
||||||
Connection conn = factory.createConnection();
|
|
||||||
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
conn.start();
|
|
||||||
MessageConsumer consumer = sess.createConsumer(AdvisorySupport.getNetworkBridgeAdvisoryTopic());
|
|
||||||
|
|
||||||
ActiveMQMessage advisory = (ActiveMQMessage) consumer.receive(2000);
|
|
||||||
assertNotNull(advisory);
|
|
||||||
assertTrue(advisory.getDataStructure() instanceof BrokerInfo);
|
|
||||||
assertTrue(advisory.getBooleanProperty("started"));
|
|
||||||
assertCreatedByDuplex(advisory.getBooleanProperty("createdByDuplex"));
|
|
||||||
|
|
||||||
broker2.stop();
|
|
||||||
broker2.waitUntilStopped();
|
|
||||||
|
|
||||||
advisory = (ActiveMQMessage) consumer.receive(2000);
|
|
||||||
assertNotNull(advisory);
|
|
||||||
assertTrue(advisory.getDataStructure() instanceof BrokerInfo);
|
|
||||||
assertFalse(advisory.getBooleanProperty("started"));
|
|
||||||
|
|
||||||
consumer = sess.createConsumer(AdvisorySupport.getNetworkBridgeAdvisoryTopic());
|
|
||||||
advisory = (ActiveMQMessage) consumer.receive(1000);
|
|
||||||
assertNull(advisory);
|
|
||||||
|
|
||||||
conn.close();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void assertCreatedByDuplex(boolean createdByDuplex) {
|
|
||||||
assertFalse(createdByDuplex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createBroker1() throws Exception {
|
|
||||||
broker1 = BrokerFactory.createBroker(new URI("xbean:org/apache/activemq/network/reconnect-broker1.xml"));
|
|
||||||
broker1.start();
|
|
||||||
broker1.waitUntilStarted();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createBroker2() throws Exception {
|
|
||||||
broker2 = BrokerFactory.createBroker(new URI("xbean:org/apache/activemq/network/reconnect-broker2.xml"));
|
|
||||||
broker2.start();
|
|
||||||
broker2.waitUntilStarted();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
broker1.stop();
|
|
||||||
broker1.waitUntilStopped();
|
|
||||||
|
|
||||||
broker2.stop();
|
|
||||||
broker2.waitUntilStopped();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- this file can only be parsed using the xbean-spring library -->
|
|
||||||
<!-- START SNIPPET: xbean -->
|
|
||||||
<beans
|
|
||||||
xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
|
|
||||||
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
|
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
|
|
||||||
|
|
||||||
<broker xmlns="http://activemq.apache.org/schema/core">
|
|
||||||
<destinations>
|
|
||||||
<queue physicalName="FOO.BAR" />
|
|
||||||
<topic physicalName="SOME.TOPIC" />
|
|
||||||
</destinations>
|
|
||||||
|
|
||||||
</broker>
|
|
||||||
|
|
||||||
</beans>
|
|
||||||
<!-- END SNIPPET: xbean -->
|
|
|
@ -1,46 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- this file can only be parsed using the xbean-spring library -->
|
|
||||||
<!-- START SNIPPET: xbean -->
|
|
||||||
<beans
|
|
||||||
xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
|
|
||||||
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
|
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
|
|
||||||
|
|
||||||
<broker xmlns="http://activemq.apache.org/schema/core">
|
|
||||||
<destinationPolicy>
|
|
||||||
<policyMap>
|
|
||||||
<policyEntries>
|
|
||||||
<policyEntry queue="TEST.>" allConsumersExclusiveByDefault="true"/>
|
|
||||||
</policyEntries>
|
|
||||||
</policyMap>
|
|
||||||
</destinationPolicy>
|
|
||||||
<destinations>
|
|
||||||
<queue physicalName="TEST.QUEUE1"/>
|
|
||||||
<queue physicalName="TEST.QUEUE2"/>
|
|
||||||
<queue physicalName="TEST.QUEUE3"/>
|
|
||||||
</destinations>
|
|
||||||
</broker>
|
|
||||||
|
|
||||||
</beans>
|
|
||||||
<!-- END SNIPPET: xbean -->
|
|
|
@ -1,84 +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.broker.ft;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.util.LeaseLockerIOExceptionHandler;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class DbRestartJDBCQueueMasterSlaveLeaseQuiesceTest extends DbRestartJDBCQueueMasterSlaveLeaseTest {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(DbRestartJDBCQueueMasterSlaveLeaseQuiesceTest.class);
|
|
||||||
|
|
||||||
private long restartDelay = 2000;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureBroker(BrokerService brokerService) {
|
|
||||||
// master and slave survive db restart and retain master/slave status
|
|
||||||
LeaseLockerIOExceptionHandler stopConnectors = new LeaseLockerIOExceptionHandler();
|
|
||||||
brokerService.setIoExceptionHandler(stopConnectors);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void delayTillRestartRequired() {
|
|
||||||
if (restartDelay > 2000) {
|
|
||||||
LOG.info("delay for more than lease quantum. While Db is offline, master should stay alive but could loose lease");
|
|
||||||
} else {
|
|
||||||
LOG.info("delay for less than lease quantum. While Db is offline, master should stay alive");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
TimeUnit.MILLISECONDS.sleep(restartDelay);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void verifyExpectedBroker(int inflightMessageCount) {
|
|
||||||
if (inflightMessageCount == 0 || (inflightMessageCount == failureCount + 10 && restartDelay <= 500)) {
|
|
||||||
assertEquals("connected to master", master.getBrokerName(), ((ActiveMQConnection) sendConnection).getBrokerName());
|
|
||||||
} else {
|
|
||||||
// lease expired while DB was offline, either or master/slave can grab it so assert is not deterministic
|
|
||||||
// but we still need to validate sent == received
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
restartDelay = 2000;
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSendReceiveWithLeaseExpiry() throws Exception {
|
|
||||||
restartDelay = 10000;
|
|
||||||
testSendReceive();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore this test case
|
|
||||||
@Override
|
|
||||||
public void testAdvisory() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testSendReceive() throws Exception {
|
|
||||||
// Ignore this test for now, see AMQ-4975
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +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.broker.ft;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.jdbc.LeaseDatabaseLocker;
|
|
||||||
import org.apache.activemq.util.LeaseLockerIOExceptionHandler;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class DbRestartJDBCQueueMasterSlaveLeaseTest extends DbRestartJDBCQueueMasterSlaveTest {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(DbRestartJDBCQueueMasterSlaveLeaseTest.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureJdbcPersistenceAdapter(JDBCPersistenceAdapter persistenceAdapter) throws IOException {
|
|
||||||
super.configureJdbcPersistenceAdapter(persistenceAdapter);
|
|
||||||
persistenceAdapter.setLocker(new LeaseDatabaseLocker());
|
|
||||||
persistenceAdapter.getLocker().setLockAcquireSleepInterval(getLockAcquireSleepInterval());
|
|
||||||
persistenceAdapter.setLockKeepAlivePeriod(getLockKeepAlivePeriod());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureBroker(BrokerService brokerService) {
|
|
||||||
//let the brokers die on exception and master should have lease on restart
|
|
||||||
// which will delay slave start till it expires
|
|
||||||
LeaseLockerIOExceptionHandler ioExceptionHandler = new LeaseLockerIOExceptionHandler();
|
|
||||||
ioExceptionHandler.setIgnoreSQLExceptions(false);
|
|
||||||
ioExceptionHandler.setStopStartConnectors(false);
|
|
||||||
ioExceptionHandler.setResumeCheckSleepPeriod(500L);
|
|
||||||
brokerService.setIoExceptionHandler(ioExceptionHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getLockKeepAlivePeriod() {
|
|
||||||
return 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getLockAcquireSleepInterval() {
|
|
||||||
return 8000;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,155 +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.broker.ft;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TransactionRolledBackException;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.command.ActiveMQMessage;
|
|
||||||
import org.apache.activemq.command.MessageId;
|
|
||||||
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
|
||||||
import org.apache.derby.jdbc.EmbeddedDataSource;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class DbRestartJDBCQueueMasterSlaveTest extends JDBCQueueMasterSlaveTest {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(DbRestartJDBCQueueMasterSlaveTest.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void messageSent() throws Exception {
|
|
||||||
verifyExpectedBroker(inflightMessageCount);
|
|
||||||
if (++inflightMessageCount == failureCount) {
|
|
||||||
LOG.info("STOPPING DB!@!!!!");
|
|
||||||
final EmbeddedDataSource ds = ((SyncCreateDataSource) getExistingDataSource()).getDelegate();
|
|
||||||
ds.setShutdownDatabase("shutdown");
|
|
||||||
LOG.info("DB STOPPED!@!!!!");
|
|
||||||
|
|
||||||
Thread dbRestartThread = new Thread("db-re-start-thread") {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
delayTillRestartRequired();
|
|
||||||
ds.setShutdownDatabase("false");
|
|
||||||
LOG.info("DB RESTARTED!@!!!!");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
dbRestartThread.start();
|
|
||||||
}
|
|
||||||
verifyExpectedBroker(inflightMessageCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void verifyExpectedBroker(int inflightMessageCount) {
|
|
||||||
if (inflightMessageCount == 0) {
|
|
||||||
assertEquals("connected to master", master.getBrokerName(), ((ActiveMQConnection) sendConnection).getBrokerName());
|
|
||||||
} else if (inflightMessageCount == failureCount + 10) {
|
|
||||||
assertEquals("connected to slave, count:" + inflightMessageCount, slave.get().getBrokerName(), ((ActiveMQConnection) sendConnection).getBrokerName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void delayTillRestartRequired() {
|
|
||||||
LOG.info("Waiting for master broker to Stop");
|
|
||||||
master.waitUntilStopped();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void sendToProducer(MessageProducer producer,
|
|
||||||
Destination producerDestination,
|
|
||||||
Message message) throws JMSException {
|
|
||||||
producer.send(producerDestination, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Session createReceiveSession(Connection receiveConnection) throws Exception {
|
|
||||||
return receiveConnection.createSession(true, Session.SESSION_TRANSACTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void consumeMessage(Message message, List<Message> messageList) {
|
|
||||||
try {
|
|
||||||
receiveSession.commit();
|
|
||||||
super.consumeMessage(message, messageList);
|
|
||||||
} catch (JMSException e) {
|
|
||||||
LOG.info("Failed to commit message receipt: " + message, e);
|
|
||||||
try {
|
|
||||||
receiveSession.rollback();
|
|
||||||
} catch (JMSException ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e instanceof TransactionRolledBackException) {
|
|
||||||
TransactionRolledBackException transactionRolledBackException = (TransactionRolledBackException) e;
|
|
||||||
if (transactionRolledBackException.getMessage().indexOf("in doubt") != -1) {
|
|
||||||
// failover chucked bc there is a missing reply to a commit.
|
|
||||||
// failover is involved b/c the store exception is handled broker side and the client just
|
|
||||||
// sees a disconnect (socket.close()).
|
|
||||||
// If the client needs to be aware of the failure then it should not use IOExceptionHandler
|
|
||||||
// so that the exception will propagate back
|
|
||||||
|
|
||||||
// for this test case:
|
|
||||||
// the commit may have got there and the reply is lost "or" the commit may be lost.
|
|
||||||
// so we may or may not get a resend.
|
|
||||||
//
|
|
||||||
// At the application level we need to determine if the message is there or not which is not trivial
|
|
||||||
// for this test we assert received == sent
|
|
||||||
// so we need to know whether the message will be replayed.
|
|
||||||
// we can ask the store b/c we know it is jdbc - guess we could go through a destination
|
|
||||||
// message store interface also or use jmx
|
|
||||||
java.sql.Connection dbConnection = null;
|
|
||||||
try {
|
|
||||||
ActiveMQMessage mqMessage = (ActiveMQMessage) message;
|
|
||||||
MessageId id = mqMessage.getMessageId();
|
|
||||||
dbConnection = sharedDs.getConnection();
|
|
||||||
PreparedStatement s = dbConnection.prepareStatement(((JDBCPersistenceAdapter) connectedToBroker().getPersistenceAdapter()).getStatements().getFindMessageStatement());
|
|
||||||
s.setString(1, id.getProducerId().toString());
|
|
||||||
s.setLong(2, id.getProducerSequenceId());
|
|
||||||
ResultSet rs = s.executeQuery();
|
|
||||||
|
|
||||||
if (!rs.next()) {
|
|
||||||
// message is gone, so lets count it as consumed
|
|
||||||
LOG.info("On TransactionRolledBackException we know that the ack/commit got there b/c message is gone so we count it: " + mqMessage);
|
|
||||||
super.consumeMessage(message, messageList);
|
|
||||||
} else {
|
|
||||||
LOG.info("On TransactionRolledBackException we know that the ack/commit was lost so we expect a replay of: " + mqMessage);
|
|
||||||
}
|
|
||||||
} catch (Exception dbe) {
|
|
||||||
dbe.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
dbConnection.close();
|
|
||||||
} catch (SQLException e1) {
|
|
||||||
e1.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private BrokerService connectedToBroker() {
|
|
||||||
return ((ActiveMQConnection) receiveConnection).getBrokerInfo().getBrokerName().equals("master") ? master : slave.get();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,165 +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.broker.ft;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.ExceptionListener;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.JmsTopicSendReceiveWithTwoConnectionsTest;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.store.jdbc.DataSourceServiceSupport;
|
|
||||||
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
|
||||||
import org.apache.activemq.util.DefaultIOExceptionHandler;
|
|
||||||
import org.apache.activemq.util.IOHelper;
|
|
||||||
import org.apache.derby.jdbc.EmbeddedDataSource;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class DbRestartJDBCQueueTest extends JmsTopicSendReceiveWithTwoConnectionsTest implements ExceptionListener {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(DbRestartJDBCQueueTest.class);
|
|
||||||
|
|
||||||
public boolean transactedSends = false;
|
|
||||||
public int failureCount = 25; // or 20 for even tx batch boundary
|
|
||||||
|
|
||||||
int inflightMessageCount = 0;
|
|
||||||
EmbeddedDataSource sharedDs;
|
|
||||||
BrokerService broker;
|
|
||||||
final CountDownLatch restartDBLatch = new CountDownLatch(1);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
setAutoFail(true);
|
|
||||||
topic = false;
|
|
||||||
verbose = true;
|
|
||||||
// startup db
|
|
||||||
sharedDs = (EmbeddedDataSource) DataSourceServiceSupport.createDataSource(IOHelper.getDefaultDataDirectory());
|
|
||||||
|
|
||||||
broker = new BrokerService();
|
|
||||||
|
|
||||||
DefaultIOExceptionHandler handler = new DefaultIOExceptionHandler();
|
|
||||||
handler.setIgnoreSQLExceptions(false);
|
|
||||||
handler.setStopStartConnectors(true);
|
|
||||||
broker.setIoExceptionHandler(handler);
|
|
||||||
broker.addConnector("tcp://localhost:0");
|
|
||||||
broker.setUseJmx(false);
|
|
||||||
broker.setPersistent(true);
|
|
||||||
broker.setDeleteAllMessagesOnStartup(true);
|
|
||||||
JDBCPersistenceAdapter persistenceAdapter = new JDBCPersistenceAdapter();
|
|
||||||
persistenceAdapter.setDataSource(sharedDs);
|
|
||||||
persistenceAdapter.setUseLock(false);
|
|
||||||
persistenceAdapter.setLockKeepAlivePeriod(500);
|
|
||||||
persistenceAdapter.getLocker().setLockAcquireSleepInterval(500);
|
|
||||||
broker.setPersistenceAdapter(persistenceAdapter);
|
|
||||||
broker.start();
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
broker.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Session createSendSession(Connection sendConnection) throws Exception {
|
|
||||||
if (transactedSends) {
|
|
||||||
return sendConnection.createSession(true, Session.SESSION_TRANSACTED);
|
|
||||||
} else {
|
|
||||||
return sendConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
ActiveMQConnectionFactory f = new ActiveMQConnectionFactory("failover://" + broker.getTransportConnectors().get(0).getPublishableConnectString());
|
|
||||||
f.setExceptionListener(this);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void messageSent() throws Exception {
|
|
||||||
if (++inflightMessageCount == failureCount) {
|
|
||||||
LOG.info("STOPPING DB!@!!!!");
|
|
||||||
final EmbeddedDataSource ds = sharedDs;
|
|
||||||
ds.setShutdownDatabase("shutdown");
|
|
||||||
try {
|
|
||||||
ds.getConnection();
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
LOG.info("DB STOPPED!@!!!!");
|
|
||||||
|
|
||||||
Thread dbRestartThread = new Thread("db-re-start-thread") {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
LOG.info("Sleeping for 10 seconds before allowing db restart");
|
|
||||||
try {
|
|
||||||
restartDBLatch.await(10, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
ds.setShutdownDatabase("false");
|
|
||||||
LOG.info("DB RESTARTED!@!!!!");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
dbRestartThread.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void sendToProducer(MessageProducer producer,
|
|
||||||
Destination producerDestination,
|
|
||||||
Message message) throws JMSException {
|
|
||||||
{
|
|
||||||
// do some retries as db failures filter back to the client until broker sees
|
|
||||||
// db lock failure and shuts down
|
|
||||||
boolean sent = false;
|
|
||||||
do {
|
|
||||||
try {
|
|
||||||
producer.send(producerDestination, message);
|
|
||||||
|
|
||||||
if (transactedSends && ((inflightMessageCount + 1) % 10 == 0 || (inflightMessageCount + 1) >= messageCount)) {
|
|
||||||
LOG.info("committing on send: " + inflightMessageCount + " message: " + message);
|
|
||||||
session.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
sent = true;
|
|
||||||
} catch (JMSException e) {
|
|
||||||
LOG.info("Exception on producer send:", e);
|
|
||||||
try {
|
|
||||||
Thread.sleep(2000);
|
|
||||||
} catch (InterruptedException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!sent);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onException(JMSException exception) {
|
|
||||||
LOG.error("exception on connection: ", exception);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,111 +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.broker.ft;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.TransportConnector;
|
|
||||||
import org.apache.activemq.store.jdbc.DataSourceServiceSupport;
|
|
||||||
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
|
||||||
import org.apache.activemq.util.DefaultIOExceptionHandler;
|
|
||||||
import org.apache.activemq.util.IOHelper;
|
|
||||||
import org.apache.derby.jdbc.EmbeddedDataSource;
|
|
||||||
|
|
||||||
public class JDBCQueueMasterSlaveTest extends QueueMasterSlaveTestSupport {
|
|
||||||
|
|
||||||
protected DataSource sharedDs;
|
|
||||||
protected String MASTER_URL = "tcp://localhost:62001";
|
|
||||||
protected String SLAVE_URL = "tcp://localhost:62002";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
// startup db
|
|
||||||
sharedDs = new SyncCreateDataSource((EmbeddedDataSource) DataSourceServiceSupport.createDataSource(IOHelper.getDefaultDataDirectory()));
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createMaster() throws Exception {
|
|
||||||
master = new BrokerService();
|
|
||||||
master.setBrokerName("master");
|
|
||||||
master.addConnector(MASTER_URL);
|
|
||||||
master.setUseJmx(false);
|
|
||||||
master.setPersistent(true);
|
|
||||||
master.setDeleteAllMessagesOnStartup(true);
|
|
||||||
JDBCPersistenceAdapter persistenceAdapter = new JDBCPersistenceAdapter();
|
|
||||||
persistenceAdapter.setDataSource(getExistingDataSource());
|
|
||||||
configureJdbcPersistenceAdapter(persistenceAdapter);
|
|
||||||
master.setPersistenceAdapter(persistenceAdapter);
|
|
||||||
configureBroker(master);
|
|
||||||
master.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void configureBroker(BrokerService brokerService) {
|
|
||||||
DefaultIOExceptionHandler stopBrokerOnStoreException = new DefaultIOExceptionHandler();
|
|
||||||
// we want any store io exception to stop the broker
|
|
||||||
stopBrokerOnStoreException.setIgnoreSQLExceptions(false);
|
|
||||||
brokerService.setIoExceptionHandler(stopBrokerOnStoreException);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createSlave() throws Exception {
|
|
||||||
// use a separate thread as the slave will block waiting for
|
|
||||||
// the exclusive db lock
|
|
||||||
Thread t = new Thread() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
BrokerService broker = new BrokerService();
|
|
||||||
broker.setBrokerName("slave");
|
|
||||||
TransportConnector connector = new TransportConnector();
|
|
||||||
connector.setUri(new URI(SLAVE_URL));
|
|
||||||
broker.addConnector(connector);
|
|
||||||
// no need for broker.setMasterConnectorURI(masterConnectorURI)
|
|
||||||
// as the db lock provides the slave/master initialisation
|
|
||||||
broker.setUseJmx(false);
|
|
||||||
broker.setPersistent(true);
|
|
||||||
JDBCPersistenceAdapter persistenceAdapter = new JDBCPersistenceAdapter();
|
|
||||||
persistenceAdapter.setDataSource(getExistingDataSource());
|
|
||||||
persistenceAdapter.setCreateTablesOnStartup(false);
|
|
||||||
broker.setPersistenceAdapter(persistenceAdapter);
|
|
||||||
configureJdbcPersistenceAdapter(persistenceAdapter);
|
|
||||||
configureBroker(broker);
|
|
||||||
broker.start();
|
|
||||||
slave.set(broker);
|
|
||||||
slaveStarted.countDown();
|
|
||||||
} catch (IllegalStateException expectedOnShutdown) {
|
|
||||||
} catch (Exception e) {
|
|
||||||
fail("failed to start slave broker, reason:" + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
t.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void configureJdbcPersistenceAdapter(JDBCPersistenceAdapter persistenceAdapter) throws IOException {
|
|
||||||
persistenceAdapter.setLockKeepAlivePeriod(500);
|
|
||||||
persistenceAdapter.getLocker().setLockAcquireSleepInterval(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected DataSource getExistingDataSource() throws Exception {
|
|
||||||
return sharedDs;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,94 +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.broker.ft;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.TransportConnector;
|
|
||||||
import org.apache.activemq.leveldb.LevelDBStore;
|
|
||||||
import org.junit.Ignore;
|
|
||||||
|
|
||||||
public class QueueMasterSlaveSingleUrlTest extends QueueMasterSlaveTestSupport {
|
|
||||||
|
|
||||||
private final String brokerUrl = "tcp://localhost:62001";
|
|
||||||
private final String singleUriString = "failover://(" + brokerUrl + ")?randomize=false";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
setAutoFail(true);
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
return new ActiveMQConnectionFactory(singleUriString);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createMaster() throws Exception {
|
|
||||||
master = new BrokerService();
|
|
||||||
master.setBrokerName("shared-master");
|
|
||||||
configureSharedPersistenceAdapter(master);
|
|
||||||
master.addConnector(brokerUrl);
|
|
||||||
master.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureSharedPersistenceAdapter(BrokerService broker) throws Exception {
|
|
||||||
LevelDBStore adapter = new LevelDBStore();
|
|
||||||
adapter.setDirectory(new File("shared"));
|
|
||||||
broker.setPersistenceAdapter(adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createSlave() throws Exception {
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
BrokerService broker = new BrokerService();
|
|
||||||
broker.setBrokerName("shared-slave");
|
|
||||||
configureSharedPersistenceAdapter(broker);
|
|
||||||
// add transport as a service so that it is bound on start, after store started
|
|
||||||
final TransportConnector tConnector = new TransportConnector();
|
|
||||||
tConnector.setUri(new URI(brokerUrl));
|
|
||||||
broker.addConnector(tConnector);
|
|
||||||
|
|
||||||
broker.start();
|
|
||||||
slave.set(broker);
|
|
||||||
slaveStarted.countDown();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// The @Ignore is just here for documentation, since this is a JUnit3 test
|
|
||||||
// I added the sleep because without it the two other test cases fail. I haven't looked into it, but
|
|
||||||
// my guess whatever setUp does isn't really finished when the teardown runs.
|
|
||||||
@Ignore("See https://issues.apache.org/jira/browse/AMQ-5164")
|
|
||||||
@Override
|
|
||||||
public void testAdvisory() throws Exception {
|
|
||||||
Thread.sleep(5 * 1000);
|
|
||||||
//super.testAdvisory();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,156 +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.broker.ft;
|
|
||||||
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.TextMessage;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.JmsTopicSendReceiveWithTwoConnectionsTest;
|
|
||||||
import org.apache.activemq.advisory.AdvisorySupport;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
|
||||||
import org.apache.activemq.xbean.BrokerFactoryBean;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test failover for Queues
|
|
||||||
*/
|
|
||||||
abstract public class QueueMasterSlaveTestSupport extends JmsTopicSendReceiveWithTwoConnectionsTest {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(QueueMasterSlaveTestSupport.class);
|
|
||||||
|
|
||||||
protected BrokerService master;
|
|
||||||
protected AtomicReference<BrokerService> slave = new AtomicReference<>();
|
|
||||||
protected CountDownLatch slaveStarted = new CountDownLatch(1);
|
|
||||||
protected int inflightMessageCount;
|
|
||||||
protected int failureCount = 50;
|
|
||||||
protected String uriString = "failover://(tcp://localhost:62001,tcp://localhost:62002)?randomize=false&useExponentialBackOff=false";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
setMaxTestTime(TimeUnit.MINUTES.toMillis(10));
|
|
||||||
setAutoFail(true);
|
|
||||||
if (System.getProperty("basedir") == null) {
|
|
||||||
File file = new File(".");
|
|
||||||
System.setProperty("basedir", file.getAbsolutePath());
|
|
||||||
}
|
|
||||||
super.messageCount = 500;
|
|
||||||
failureCount = super.messageCount / 2;
|
|
||||||
super.topic = isTopic();
|
|
||||||
createMaster();
|
|
||||||
createSlave();
|
|
||||||
// wait for thing to connect
|
|
||||||
Thread.sleep(1000);
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getSlaveXml() {
|
|
||||||
return "org/apache/activemq/broker/ft/slave.xml";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getMasterXml() {
|
|
||||||
return "org/apache/activemq/broker/ft/master.xml";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
master.stop();
|
|
||||||
master.waitUntilStopped();
|
|
||||||
slaveStarted.await(60, TimeUnit.SECONDS);
|
|
||||||
BrokerService brokerService = slave.get();
|
|
||||||
if (brokerService != null) {
|
|
||||||
brokerService.stop();
|
|
||||||
}
|
|
||||||
master.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
return new ActiveMQConnectionFactory(uriString);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void messageSent() throws Exception {
|
|
||||||
if (++inflightMessageCount == failureCount) {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
LOG.error("MASTER STOPPED!@!!!!");
|
|
||||||
master.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isTopic() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void createMaster() throws Exception {
|
|
||||||
BrokerFactoryBean brokerFactory = new BrokerFactoryBean(new ClassPathResource(getMasterXml()));
|
|
||||||
brokerFactory.afterPropertiesSet();
|
|
||||||
master = brokerFactory.getBroker();
|
|
||||||
master.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void createSlave() throws Exception {
|
|
||||||
BrokerFactoryBean brokerFactory = new BrokerFactoryBean(new ClassPathResource(getSlaveXml()));
|
|
||||||
brokerFactory.afterPropertiesSet();
|
|
||||||
BrokerService broker = brokerFactory.getBroker();
|
|
||||||
broker.start();
|
|
||||||
slave.set(broker);
|
|
||||||
slaveStarted.countDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testVirtualTopicFailover() throws Exception {
|
|
||||||
|
|
||||||
MessageConsumer qConsumer = session.createConsumer(new ActiveMQQueue("Consumer.A.VirtualTopic.TA1"));
|
|
||||||
assertNull("No message there yet", qConsumer.receive(1000));
|
|
||||||
qConsumer.close();
|
|
||||||
assertTrue(!master.isSlave());
|
|
||||||
master.stop();
|
|
||||||
assertTrue("slave started", slaveStarted.await(60, TimeUnit.SECONDS));
|
|
||||||
assertTrue(!slave.get().isSlave());
|
|
||||||
|
|
||||||
final String text = "ForUWhenSlaveKicksIn";
|
|
||||||
producer.send(new ActiveMQTopic("VirtualTopic.TA1"), session.createTextMessage(text));
|
|
||||||
|
|
||||||
qConsumer = session.createConsumer(new ActiveMQQueue("Consumer.A.VirtualTopic.TA1"));
|
|
||||||
|
|
||||||
javax.jms.Message message = qConsumer.receive(4000);
|
|
||||||
assertNotNull("Get message after failover", message);
|
|
||||||
assertEquals("correct message", text, ((TextMessage) message).getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAdvisory() throws Exception {
|
|
||||||
MessageConsumer advConsumer = session.createConsumer(AdvisorySupport.getMasterBrokerAdvisoryTopic());
|
|
||||||
|
|
||||||
master.stop();
|
|
||||||
assertTrue("slave started", slaveStarted.await(60, TimeUnit.SECONDS));
|
|
||||||
LOG.info("slave started");
|
|
||||||
Message advisoryMessage = advConsumer.receive(5000);
|
|
||||||
LOG.info("received " + advisoryMessage);
|
|
||||||
assertNotNull("Didn't received advisory", advisoryMessage);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +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.broker.ft;
|
|
||||||
|
|
||||||
public class QueueMasterSlaveTestUsingSharedFileTest extends QueueMasterSlaveTestSupport {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getSlaveXml() {
|
|
||||||
return "org/apache/activemq/broker/ft/sharedFileSlave.xml";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getMasterXml() {
|
|
||||||
return "org/apache/activemq/broker/ft/sharedFileMaster.xml";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createSlave() throws Exception {
|
|
||||||
// Start the Brokers async since starting them up could be a blocking operation..
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
QueueMasterSlaveTestUsingSharedFileTest.super.createSlave();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,89 +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.broker.ft;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.SQLFeatureNotSupportedException;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import org.apache.derby.jdbc.EmbeddedDataSource;
|
|
||||||
|
|
||||||
// prevent concurrent calls from attempting to create the db at the same time
|
|
||||||
// can result in "already exists in this jvm" errors
|
|
||||||
|
|
||||||
public class SyncCreateDataSource implements DataSource {
|
|
||||||
|
|
||||||
final EmbeddedDataSource delegate;
|
|
||||||
|
|
||||||
SyncCreateDataSource(EmbeddedDataSource dataSource) {
|
|
||||||
this.delegate = dataSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Connection getConnection() throws SQLException {
|
|
||||||
synchronized (this) {
|
|
||||||
return delegate.getConnection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Connection getConnection(String username, String password) throws SQLException {
|
|
||||||
synchronized (this) {
|
|
||||||
return delegate.getConnection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PrintWriter getLogWriter() throws SQLException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLogWriter(PrintWriter out) throws SQLException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLoginTimeout() throws SQLException {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLoginTimeout(int seconds) throws SQLException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T unwrap(Class<T> iface) throws SQLException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmbeddedDataSource getDelegate() {
|
|
||||||
return delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,120 +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.broker.ft;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.TransportConnector;
|
|
||||||
import org.apache.activemq.store.jdbc.DataSourceServiceSupport;
|
|
||||||
import org.apache.activemq.store.jdbc.LeaseDatabaseLocker;
|
|
||||||
import org.apache.activemq.store.jdbc.Statements;
|
|
||||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
|
||||||
import org.apache.activemq.util.DefaultIOExceptionHandler;
|
|
||||||
import org.apache.activemq.util.IOHelper;
|
|
||||||
import org.apache.derby.jdbc.EmbeddedDataSource;
|
|
||||||
|
|
||||||
public class kahaDbJdbcLeaseQueueMasterSlaveTest extends QueueMasterSlaveTestSupport {
|
|
||||||
|
|
||||||
protected DataSource sharedDs;
|
|
||||||
protected String MASTER_URL = "tcp://localhost:62001";
|
|
||||||
protected String SLAVE_URL = "tcp://localhost:62002";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
// startup db
|
|
||||||
sharedDs = new SyncCreateDataSource((EmbeddedDataSource) DataSourceServiceSupport.createDataSource(IOHelper.getDefaultDataDirectory()));
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createMaster() throws Exception {
|
|
||||||
master = new BrokerService();
|
|
||||||
master.setBrokerName("master");
|
|
||||||
master.addConnector(MASTER_URL);
|
|
||||||
master.setUseJmx(false);
|
|
||||||
master.setPersistent(true);
|
|
||||||
master.setDeleteAllMessagesOnStartup(true);
|
|
||||||
KahaDBPersistenceAdapter kahaDBPersistenceAdapter = (KahaDBPersistenceAdapter) master.getPersistenceAdapter();
|
|
||||||
LeaseDatabaseLocker leaseDatabaseLocker = new LeaseDatabaseLocker();
|
|
||||||
leaseDatabaseLocker.setCreateTablesOnStartup(true);
|
|
||||||
leaseDatabaseLocker.setDataSource(getExistingDataSource());
|
|
||||||
leaseDatabaseLocker.setStatements(new Statements());
|
|
||||||
kahaDBPersistenceAdapter.setLocker(leaseDatabaseLocker);
|
|
||||||
configureLocker(kahaDBPersistenceAdapter);
|
|
||||||
configureBroker(master);
|
|
||||||
master.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void configureBroker(BrokerService brokerService) {
|
|
||||||
DefaultIOExceptionHandler stopBrokerOnStoreException = new DefaultIOExceptionHandler();
|
|
||||||
// we want any store io exception to stop the broker
|
|
||||||
stopBrokerOnStoreException.setIgnoreSQLExceptions(false);
|
|
||||||
brokerService.setIoExceptionHandler(stopBrokerOnStoreException);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createSlave() throws Exception {
|
|
||||||
// use a separate thread as the slave will block waiting for
|
|
||||||
// the exclusive db lock
|
|
||||||
Thread t = new Thread() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
BrokerService broker = new BrokerService();
|
|
||||||
broker.setBrokerName("slave");
|
|
||||||
TransportConnector connector = new TransportConnector();
|
|
||||||
connector.setUri(new URI(SLAVE_URL));
|
|
||||||
broker.addConnector(connector);
|
|
||||||
broker.setUseJmx(false);
|
|
||||||
broker.setPersistent(true);
|
|
||||||
KahaDBPersistenceAdapter kahaDBPersistenceAdapter = (KahaDBPersistenceAdapter) broker.getPersistenceAdapter();
|
|
||||||
LeaseDatabaseLocker leaseDatabaseLocker = new LeaseDatabaseLocker();
|
|
||||||
leaseDatabaseLocker.setDataSource(getExistingDataSource());
|
|
||||||
leaseDatabaseLocker.setStatements(new Statements());
|
|
||||||
kahaDBPersistenceAdapter.setLocker(leaseDatabaseLocker);
|
|
||||||
configureLocker(kahaDBPersistenceAdapter);
|
|
||||||
configureBroker(broker);
|
|
||||||
broker.start();
|
|
||||||
slave.set(broker);
|
|
||||||
slaveStarted.countDown();
|
|
||||||
} catch (IllegalStateException expectedOnShutdown) {
|
|
||||||
} catch (Exception e) {
|
|
||||||
fail("failed to start slave broker, reason:" + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
t.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void configureLocker(KahaDBPersistenceAdapter kahaDBPersistenceAdapter) throws IOException {
|
|
||||||
kahaDBPersistenceAdapter.setLockKeepAlivePeriod(500);
|
|
||||||
kahaDBPersistenceAdapter.getLocker().setLockAcquireSleepInterval(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testVirtualTopicFailover() throws Exception {
|
|
||||||
// Ignoring for now, see AMQ-4842
|
|
||||||
}
|
|
||||||
|
|
||||||
protected DataSource getExistingDataSource() throws Exception {
|
|
||||||
return sharedDs;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,94 +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.broker.ft;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.TransportConnector;
|
|
||||||
import org.apache.activemq.store.kahadb.FilteredKahaDBPersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.kahadb.MultiKahaDBPersistenceAdapter;
|
|
||||||
|
|
||||||
public class mKahaDbQueueMasterSlaveTest extends QueueMasterSlaveTestSupport {
|
|
||||||
|
|
||||||
protected String MASTER_URL = "tcp://localhost:62001";
|
|
||||||
protected String SLAVE_URL = "tcp://localhost:62002";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createMaster() throws Exception {
|
|
||||||
master = new BrokerService();
|
|
||||||
master.setBrokerName("master");
|
|
||||||
master.addConnector(MASTER_URL);
|
|
||||||
master.setUseJmx(false);
|
|
||||||
master.setPersistent(true);
|
|
||||||
master.setDeleteAllMessagesOnStartup(true);
|
|
||||||
|
|
||||||
MultiKahaDBPersistenceAdapter mKahaDB = new MultiKahaDBPersistenceAdapter();
|
|
||||||
List<FilteredKahaDBPersistenceAdapter> adapters = new LinkedList<>();
|
|
||||||
FilteredKahaDBPersistenceAdapter defaultEntry = new FilteredKahaDBPersistenceAdapter();
|
|
||||||
defaultEntry.setPersistenceAdapter(new KahaDBPersistenceAdapter());
|
|
||||||
defaultEntry.setPerDestination(true);
|
|
||||||
adapters.add(defaultEntry);
|
|
||||||
|
|
||||||
mKahaDB.setFilteredPersistenceAdapters(adapters);
|
|
||||||
master.setPersistenceAdapter(mKahaDB);
|
|
||||||
|
|
||||||
master.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void createSlave() throws Exception {
|
|
||||||
// use a separate thread as the slave will block waiting for
|
|
||||||
// the exclusive db lock
|
|
||||||
Thread t = new Thread() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
BrokerService broker = new BrokerService();
|
|
||||||
broker.setBrokerName("slave");
|
|
||||||
TransportConnector connector = new TransportConnector();
|
|
||||||
connector.setUri(new URI(SLAVE_URL));
|
|
||||||
broker.addConnector(connector);
|
|
||||||
// no need for broker.setMasterConnectorURI(masterConnectorURI)
|
|
||||||
// as the db lock provides the slave/master initialisation
|
|
||||||
broker.setUseJmx(false);
|
|
||||||
broker.setPersistent(true);
|
|
||||||
|
|
||||||
MultiKahaDBPersistenceAdapter mKahaDB = new MultiKahaDBPersistenceAdapter();
|
|
||||||
List<FilteredKahaDBPersistenceAdapter> adapters = new LinkedList<>();
|
|
||||||
FilteredKahaDBPersistenceAdapter defaultEntry = new FilteredKahaDBPersistenceAdapter();
|
|
||||||
defaultEntry.setPersistenceAdapter(new KahaDBPersistenceAdapter());
|
|
||||||
defaultEntry.setPerDestination(true);
|
|
||||||
adapters.add(defaultEntry);
|
|
||||||
|
|
||||||
mKahaDB.setFilteredPersistenceAdapters(adapters);
|
|
||||||
broker.setPersistenceAdapter(mKahaDB);
|
|
||||||
broker.start();
|
|
||||||
slave.set(broker);
|
|
||||||
slaveStarted.countDown();
|
|
||||||
} catch (IllegalStateException expectedOnShutdown) {
|
|
||||||
} catch (Exception e) {
|
|
||||||
fail("failed to start slave broker, reason:" + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
t.start();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<beans
|
|
||||||
xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
|
|
||||||
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
|
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
|
||||||
|
|
||||||
<broker brokerName="shared" useJmx="false" deleteAllMessagesOnStartup="true" xmlns="http://activemq.apache.org/schema/core">
|
|
||||||
<transportConnectors>
|
|
||||||
<transportConnector uri="tcp://localhost:62001"/>
|
|
||||||
</transportConnectors>
|
|
||||||
|
|
||||||
</broker>
|
|
||||||
|
|
||||||
</beans>
|
|
|
@ -1,35 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
<beans
|
|
||||||
xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
|
|
||||||
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
|
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
|
||||||
|
|
||||||
<broker brokerName="shared" useJmx="false" deleteAllMessagesOnStartup="false" xmlns="http://activemq.apache.org/schema/core">
|
|
||||||
<transportConnectors>
|
|
||||||
<transportConnector uri="tcp://localhost:62002"/>
|
|
||||||
</transportConnectors>
|
|
||||||
|
|
||||||
|
|
||||||
</broker>
|
|
||||||
|
|
||||||
</beans>
|
|
|
@ -1,64 +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.broker;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.store.kahadb.FilteredKahaDBPersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.kahadb.MultiKahaDBPersistenceAdapter;
|
|
||||||
|
|
||||||
public class mKahaDBXARecoveryBrokerTest extends XARecoveryBrokerTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureBroker(BrokerService broker) throws Exception {
|
|
||||||
super.configureBroker(broker);
|
|
||||||
|
|
||||||
MultiKahaDBPersistenceAdapter mKahaDB = new MultiKahaDBPersistenceAdapter();
|
|
||||||
List<FilteredKahaDBPersistenceAdapter> adapters = new LinkedList<>();
|
|
||||||
FilteredKahaDBPersistenceAdapter defaultEntry = new FilteredKahaDBPersistenceAdapter();
|
|
||||||
defaultEntry.setPersistenceAdapter(new KahaDBPersistenceAdapter());
|
|
||||||
adapters.add(defaultEntry);
|
|
||||||
|
|
||||||
FilteredKahaDBPersistenceAdapter special = new FilteredKahaDBPersistenceAdapter();
|
|
||||||
special.setDestination(new ActiveMQQueue("special"));
|
|
||||||
special.setPersistenceAdapter(new KahaDBPersistenceAdapter());
|
|
||||||
adapters.add(special);
|
|
||||||
|
|
||||||
mKahaDB.setFilteredPersistenceAdapters(adapters);
|
|
||||||
broker.setPersistenceAdapter(mKahaDB);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(mKahaDBXARecoveryBrokerTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(suite());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActiveMQDestination createDestination() {
|
|
||||||
return new ActiveMQQueue("test,special");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,73 +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.broker;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.store.kahadb.FilteredKahaDBPersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.kahadb.MultiKahaDBPersistenceAdapter;
|
|
||||||
import org.apache.activemq.store.leveldb.LevelDBPersistenceAdapter;
|
|
||||||
|
|
||||||
public class mLevelDBXARecoveryBrokerTest extends XARecoveryBrokerTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configureBroker(BrokerService broker) throws Exception {
|
|
||||||
super.configureBroker(broker);
|
|
||||||
|
|
||||||
MultiKahaDBPersistenceAdapter mKahaDB = new MultiKahaDBPersistenceAdapter();
|
|
||||||
List<FilteredKahaDBPersistenceAdapter> adapters = new LinkedList<>();
|
|
||||||
FilteredKahaDBPersistenceAdapter defaultEntry = new FilteredKahaDBPersistenceAdapter();
|
|
||||||
defaultEntry.setPersistenceAdapter(new LevelDBPersistenceAdapter());
|
|
||||||
adapters.add(defaultEntry);
|
|
||||||
|
|
||||||
FilteredKahaDBPersistenceAdapter special = new FilteredKahaDBPersistenceAdapter();
|
|
||||||
special.setDestination(new ActiveMQQueue("special"));
|
|
||||||
special.setPersistenceAdapter(new LevelDBPersistenceAdapter());
|
|
||||||
adapters.add(special);
|
|
||||||
|
|
||||||
mKahaDB.setFilteredPersistenceAdapters(adapters);
|
|
||||||
broker.setPersistenceAdapter(mKahaDB);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(mLevelDBXARecoveryBrokerTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
junit.textui.TestRunner.run(suite());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActiveMQDestination createDestination() {
|
|
||||||
return new ActiveMQQueue("test,special");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testQueuePersistentPreparedAcksAvailableAfterRestartAndRollback() throws Exception {
|
|
||||||
// super.testQueuePersistentPreparedAcksAvailableAfterRestartAndRollback();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testQueuePersistentUncommittedAcksLostOnRestart() throws Exception {
|
|
||||||
// super.testQueuePersistentUncommittedAcksLostOnRestart();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,100 +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.broker.message.security;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TextMessage;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.security.MessageAuthorizationPolicy;
|
|
||||||
import org.apache.activemq.spring.ConsumerBean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class MessageAuthenticationTest extends EmbeddedBrokerTestSupport {
|
|
||||||
|
|
||||||
private Connection connection;
|
|
||||||
|
|
||||||
public void testSendInvalidMessage() throws Exception {
|
|
||||||
if (connection == null) {
|
|
||||||
connection = createConnection();
|
|
||||||
}
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
ConsumerBean messageList = new ConsumerBean();
|
|
||||||
messageList.setVerbose(true);
|
|
||||||
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
|
|
||||||
Destination destination = new ActiveMQQueue("MyQueue");
|
|
||||||
|
|
||||||
MessageConsumer c1 = session.createConsumer(destination);
|
|
||||||
|
|
||||||
c1.setMessageListener(messageList);
|
|
||||||
|
|
||||||
MessageProducer producer = session.createProducer(destination);
|
|
||||||
assertNotNull(producer);
|
|
||||||
|
|
||||||
producer.send(createMessage(session, "invalidBody", "myHeader", "xyz"));
|
|
||||||
producer.send(createMessage(session, "validBody", "myHeader", "abc"));
|
|
||||||
|
|
||||||
messageList.assertMessagesArrived(1);
|
|
||||||
assertEquals("validBody", ((TextMessage) messageList.flushMessages().get(0)).getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
private javax.jms.Message createMessage(Session session,
|
|
||||||
String body,
|
|
||||||
String header,
|
|
||||||
String value) throws JMSException {
|
|
||||||
TextMessage msg = session.createTextMessage(body);
|
|
||||||
msg.setStringProperty(header, value);
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService answer = new BrokerService();
|
|
||||||
answer.setPersistent(false);
|
|
||||||
answer.setMessageAuthorizationPolicy(new MessageAuthorizationPolicy() {
|
|
||||||
@Override
|
|
||||||
public boolean isAllowedToConsume(ConnectionContext context, Message message) {
|
|
||||||
try {
|
|
||||||
Object value = message.getProperty("myHeader");
|
|
||||||
return "abc".equals(value);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("Caught: " + e);
|
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
answer.addConnector(bindAddress);
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- this file can only be parsed using the xbean-spring library with validation off -->
|
|
||||||
<beans
|
|
||||||
xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
|
|
||||||
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
|
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
|
|
||||||
|
|
||||||
<broker xmlns="http://activemq.apache.org/schema/core">
|
|
||||||
<systemUsage>
|
|
||||||
<systemUsage>
|
|
||||||
<memoryUsage>
|
|
||||||
<memoryUsage limit="20 mb"/>
|
|
||||||
</memoryUsage>
|
|
||||||
<storeUsage>
|
|
||||||
<storeUsage limit="1 gb" name="foo"/>
|
|
||||||
</storeUsage>
|
|
||||||
<tempUsage>
|
|
||||||
<tempUsage limit="100 mb"/>
|
|
||||||
</tempUsage>
|
|
||||||
</systemUsage>
|
|
||||||
</systemUsage>
|
|
||||||
<destinations>
|
|
||||||
<queue physicalName="FOO.BAR"/>
|
|
||||||
<topic physicalName="SOME.TOPIC"/>
|
|
||||||
</destinations>
|
|
||||||
|
|
||||||
</broker>
|
|
||||||
|
|
||||||
</beans>
|
|
|
@ -1,53 +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.broker.partition;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerFactory;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.partition.PartitionBrokerPlugin;
|
|
||||||
import org.apache.activemq.partition.dto.Partitioning;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public class SpringPartitionBrokerTest extends TestCase {
|
|
||||||
|
|
||||||
public void testCreatePartitionBroker() throws Exception {
|
|
||||||
|
|
||||||
BrokerService broker = BrokerFactory.createBroker("xbean:activemq-partition.xml");
|
|
||||||
assertEquals(1, broker.getPlugins().length);
|
|
||||||
PartitionBrokerPlugin plugin = (PartitionBrokerPlugin) broker.getPlugins()[0];
|
|
||||||
Partitioning config = plugin.getConfig();
|
|
||||||
assertEquals(2, config.getBrokers().size());
|
|
||||||
|
|
||||||
String json = "{\n" +
|
|
||||||
" \"by_client_id\":{\n" +
|
|
||||||
" \"client1\":{\"ids\":[\"broker1\"]},\n" +
|
|
||||||
" \"client2\":{\"ids\":[\"broker1\",\"broker2\"]}\n" +
|
|
||||||
" },\n" +
|
|
||||||
" \"brokers\":{\n" +
|
|
||||||
" \"broker1\":\"tcp://localhost:61616\",\n" +
|
|
||||||
" \"broker2\":\"tcp://localhost:61616\"\n" +
|
|
||||||
" }\n" +
|
|
||||||
"}";
|
|
||||||
Partitioning expected = Partitioning.MAPPER.readValue(json, Partitioning.class);
|
|
||||||
assertEquals(expected.toString(), config.toString());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,177 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.policy.AbortSlowAckConsumerStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
@RunWith(value = Parameterized.class)
|
|
||||||
public class AbortSlowAckConsumer0Test extends AbortSlowConsumer0Test {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AbortSlowAckConsumer0Test.class);
|
|
||||||
protected long maxTimeSinceLastAck = 5 * 1000;
|
|
||||||
|
|
||||||
AbortSlowAckConsumerStrategy strategy;
|
|
||||||
|
|
||||||
public AbortSlowAckConsumer0Test(Boolean isTopic) {
|
|
||||||
super(isTopic);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbortSlowAckConsumerStrategy createSlowConsumerStrategy() {
|
|
||||||
AbortSlowAckConsumerStrategy strategy = new AbortSlowAckConsumerStrategy();
|
|
||||||
strategy.setAbortConnection(abortConnection);
|
|
||||||
strategy.setCheckPeriod(checkPeriod);
|
|
||||||
strategy.setMaxSlowDuration(maxSlowDuration);
|
|
||||||
strategy.setMaxTimeSinceLastAck(maxTimeSinceLastAck);
|
|
||||||
|
|
||||||
return strategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
|
|
||||||
strategy = createSlowConsumerStrategy();
|
|
||||||
underTest = strategy;
|
|
||||||
|
|
||||||
policy.setSlowConsumerStrategy(strategy);
|
|
||||||
policy.setQueuePrefetch(10);
|
|
||||||
policy.setTopicPrefetch(10);
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
broker.setDestinationPolicy(pMap);
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost");
|
|
||||||
factory.getPrefetchPolicy().setAll(1);
|
|
||||||
return factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test
|
|
||||||
public void testSlowConsumerIsAbortedViaJmx() throws Exception {
|
|
||||||
strategy.setMaxTimeSinceLastAck(500); // so jmx does the abort
|
|
||||||
super.testSlowConsumerIsAbortedViaJmx();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testZeroPrefetchConsumerIsAborted() throws Exception {
|
|
||||||
strategy.setMaxTimeSinceLastAck(2000); // Make it shorter
|
|
||||||
|
|
||||||
ActiveMQConnection conn = (ActiveMQConnection) createConnectionFactory().createConnection();
|
|
||||||
conn.setExceptionListener(this);
|
|
||||||
connections.add(conn);
|
|
||||||
|
|
||||||
Session sess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
final MessageConsumer consumer = sess.createConsumer(destination);
|
|
||||||
assertNotNull(consumer);
|
|
||||||
conn.start();
|
|
||||||
startProducers(destination, 20);
|
|
||||||
|
|
||||||
Message message = consumer.receive(5000);
|
|
||||||
assertNotNull(message);
|
|
||||||
|
|
||||||
TimeUnit.SECONDS.sleep(15);
|
|
||||||
|
|
||||||
try {
|
|
||||||
consumer.receive(5000);
|
|
||||||
fail("Slow consumer not aborted.");
|
|
||||||
} catch (Exception ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIdleConsumerCanBeAbortedNoMessages() throws Exception {
|
|
||||||
strategy.setIgnoreIdleConsumers(false);
|
|
||||||
strategy.setMaxTimeSinceLastAck(2000); // Make it shorter
|
|
||||||
|
|
||||||
ActiveMQConnection conn = (ActiveMQConnection) createConnectionFactory().createConnection();
|
|
||||||
conn.setExceptionListener(this);
|
|
||||||
connections.add(conn);
|
|
||||||
|
|
||||||
Session sess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
final MessageConsumer consumer = sess.createConsumer(destination);
|
|
||||||
assertNotNull(consumer);
|
|
||||||
conn.start();
|
|
||||||
|
|
||||||
startProducers(destination, 1);
|
|
||||||
|
|
||||||
Message message = consumer.receive(5000);
|
|
||||||
assertNotNull(message);
|
|
||||||
|
|
||||||
// Consumer needs to be closed before the receive call.
|
|
||||||
TimeUnit.SECONDS.sleep(15);
|
|
||||||
|
|
||||||
try {
|
|
||||||
consumer.receive(5000);
|
|
||||||
fail("Idle consumer not aborted.");
|
|
||||||
} catch (Exception ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIdleConsumerCanBeAborted() throws Exception {
|
|
||||||
strategy.setIgnoreIdleConsumers(false);
|
|
||||||
strategy.setMaxTimeSinceLastAck(2000); // Make it shorter
|
|
||||||
|
|
||||||
ActiveMQConnection conn = (ActiveMQConnection) createConnectionFactory().createConnection();
|
|
||||||
conn.setExceptionListener(this);
|
|
||||||
connections.add(conn);
|
|
||||||
|
|
||||||
Session sess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
final MessageConsumer consumer = sess.createConsumer(destination);
|
|
||||||
assertNotNull(consumer);
|
|
||||||
conn.start();
|
|
||||||
startProducers(destination, 1);
|
|
||||||
|
|
||||||
Message message = consumer.receive(5000);
|
|
||||||
assertNotNull(message);
|
|
||||||
message.acknowledge();
|
|
||||||
|
|
||||||
// Consumer needs to be closed before the receive call.
|
|
||||||
TimeUnit.SECONDS.sleep(15);
|
|
||||||
|
|
||||||
try {
|
|
||||||
consumer.receive(5000);
|
|
||||||
fail("Idle consumer not aborted.");
|
|
||||||
} catch (Exception ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.policy.AbortSlowAckConsumerStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.AbortSlowConsumerStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
|
|
||||||
@RunWith(value = Parameterized.class)
|
|
||||||
public class AbortSlowAckConsumer1Test extends AbortSlowConsumer1Test {
|
|
||||||
|
|
||||||
protected long maxTimeSinceLastAck = 5 * 1000;
|
|
||||||
|
|
||||||
public AbortSlowAckConsumer1Test(Boolean abortConnection, Boolean topic) {
|
|
||||||
super(abortConnection, topic);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbortSlowConsumerStrategy createSlowConsumerStrategy() {
|
|
||||||
return new AbortSlowConsumerStrategy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
|
|
||||||
AbortSlowAckConsumerStrategy strategy = new AbortSlowAckConsumerStrategy();
|
|
||||||
strategy.setAbortConnection(abortConnection);
|
|
||||||
strategy.setCheckPeriod(checkPeriod);
|
|
||||||
strategy.setMaxSlowDuration(maxSlowDuration);
|
|
||||||
strategy.setMaxTimeSinceLastAck(maxTimeSinceLastAck);
|
|
||||||
|
|
||||||
policy.setSlowConsumerStrategy(strategy);
|
|
||||||
policy.setQueuePrefetch(10);
|
|
||||||
policy.setTopicPrefetch(10);
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
broker.setDestinationPolicy(pMap);
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost");
|
|
||||||
factory.getPrefetchPolicy().setAll(1);
|
|
||||||
return factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,71 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.policy.AbortSlowAckConsumerStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.AbortSlowConsumerStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
|
|
||||||
@RunWith(value = Parameterized.class)
|
|
||||||
public class AbortSlowAckConsumer2Test extends AbortSlowConsumer2Test {
|
|
||||||
|
|
||||||
protected long maxTimeSinceLastAck = 5 * 1000;
|
|
||||||
|
|
||||||
public AbortSlowAckConsumer2Test(Boolean topic) {
|
|
||||||
super(topic);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected AbortSlowConsumerStrategy createSlowConsumerStrategy() {
|
|
||||||
return new AbortSlowConsumerStrategy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
|
|
||||||
AbortSlowAckConsumerStrategy strategy = new AbortSlowAckConsumerStrategy();
|
|
||||||
strategy.setAbortConnection(abortConnection);
|
|
||||||
strategy.setCheckPeriod(checkPeriod);
|
|
||||||
strategy.setMaxSlowDuration(maxSlowDuration);
|
|
||||||
strategy.setMaxTimeSinceLastAck(maxTimeSinceLastAck);
|
|
||||||
|
|
||||||
policy.setSlowConsumerStrategy(strategy);
|
|
||||||
policy.setQueuePrefetch(10);
|
|
||||||
policy.setTopicPrefetch(10);
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
broker.setDestinationPolicy(pMap);
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost");
|
|
||||||
factory.getPrefetchPolicy().setAll(1);
|
|
||||||
return factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,240 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.management.InstanceNotFoundException;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
import javax.management.openmbean.CompositeData;
|
|
||||||
import javax.management.openmbean.TabularData;
|
|
||||||
import java.lang.reflect.UndeclaredThrowableException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.ActiveMQMessageConsumer;
|
|
||||||
import org.apache.activemq.ActiveMQPrefetchPolicy;
|
|
||||||
import org.apache.activemq.broker.TransportConnector;
|
|
||||||
import org.apache.activemq.broker.jmx.AbortSlowConsumerStrategyViewMBean;
|
|
||||||
import org.apache.activemq.broker.jmx.DestinationViewMBean;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
|
||||||
import org.apache.activemq.util.MessageIdList;
|
|
||||||
import org.apache.activemq.util.SocketProxy;
|
|
||||||
import org.apache.activemq.util.Wait;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
@RunWith(value = Parameterized.class)
|
|
||||||
public class AbortSlowConsumer0Test extends AbortSlowConsumerBase {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AbortSlowConsumer0Test.class);
|
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "isTopic({0})")
|
|
||||||
public static Collection<Object[]> getTestParameters() {
|
|
||||||
return Arrays.asList(new Object[][]{{Boolean.TRUE}, {Boolean.FALSE}});
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbortSlowConsumer0Test(Boolean isTopic) {
|
|
||||||
this.topic = isTopic;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRegularConsumerIsNotAborted() throws Exception {
|
|
||||||
startConsumers(destination);
|
|
||||||
for (Connection c : connections) {
|
|
||||||
c.setExceptionListener(this);
|
|
||||||
}
|
|
||||||
startProducers(destination, 100);
|
|
||||||
allMessagesList.waitForMessagesToArrive(10);
|
|
||||||
allMessagesList.assertAtLeastMessagesReceived(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSlowConsumerIsAbortedViaJmx() throws Exception {
|
|
||||||
underTest.setMaxSlowDuration(60 * 1000); // so jmx does the abort
|
|
||||||
startConsumers(withPrefetch(2, destination));
|
|
||||||
Entry<MessageConsumer, MessageIdList> consumertoAbort = consumers.entrySet().iterator().next();
|
|
||||||
consumertoAbort.getValue().setProcessingDelay(8 * 1000);
|
|
||||||
for (Connection c : connections) {
|
|
||||||
c.setExceptionListener(this);
|
|
||||||
}
|
|
||||||
startProducers(destination, 100);
|
|
||||||
|
|
||||||
consumertoAbort.getValue().assertMessagesReceived(1);
|
|
||||||
|
|
||||||
ActiveMQDestination amqDest = (ActiveMQDestination) destination;
|
|
||||||
ObjectName destinationViewMBean = new ObjectName("org.apache.activemq:destinationType=" +
|
|
||||||
(amqDest.isTopic() ? "Topic" : "Queue") + ",destinationName=" + amqDest.getPhysicalName() + ",type=Broker,brokerName=localhost");
|
|
||||||
|
|
||||||
DestinationViewMBean queue = (DestinationViewMBean) broker.getManagementContext().newProxyInstance(destinationViewMBean, DestinationViewMBean.class, true);
|
|
||||||
ObjectName slowConsumerPolicyMBeanName = queue.getSlowConsumerStrategy();
|
|
||||||
|
|
||||||
assertNotNull(slowConsumerPolicyMBeanName);
|
|
||||||
|
|
||||||
AbortSlowConsumerStrategyViewMBean abortPolicy = (AbortSlowConsumerStrategyViewMBean) broker.getManagementContext().newProxyInstance(slowConsumerPolicyMBeanName, AbortSlowConsumerStrategyViewMBean.class, true);
|
|
||||||
|
|
||||||
TimeUnit.SECONDS.sleep(3);
|
|
||||||
|
|
||||||
TabularData slowOnes = abortPolicy.getSlowConsumers();
|
|
||||||
assertEquals("one slow consumers", 1, slowOnes.size());
|
|
||||||
|
|
||||||
LOG.info("slow ones:" + slowOnes);
|
|
||||||
|
|
||||||
CompositeData slowOne = (CompositeData) slowOnes.values().iterator().next();
|
|
||||||
LOG.info("Slow one: " + slowOne);
|
|
||||||
|
|
||||||
assertTrue("we have an object name", slowOne.get("subscription") instanceof ObjectName);
|
|
||||||
abortPolicy.abortConsumer((ObjectName) slowOne.get("subscription"));
|
|
||||||
|
|
||||||
consumertoAbort.getValue().assertAtMostMessagesReceived(1);
|
|
||||||
|
|
||||||
slowOnes = abortPolicy.getSlowConsumers();
|
|
||||||
assertEquals("no slow consumers left", 0, slowOnes.size());
|
|
||||||
|
|
||||||
// verify mbean gone with destination
|
|
||||||
broker.getAdminView().removeTopic(amqDest.getPhysicalName());
|
|
||||||
|
|
||||||
try {
|
|
||||||
abortPolicy.getSlowConsumers();
|
|
||||||
fail("expect not found post destination removal");
|
|
||||||
} catch (UndeclaredThrowableException expected) {
|
|
||||||
assertTrue("correct exception: " + expected.getCause(), expected.getCause() instanceof InstanceNotFoundException);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Destination withPrefetch(int i, Destination destination) {
|
|
||||||
String destWithPrefetch = ((ActiveMQDestination) destination).getPhysicalName() + "?consumer.prefetchSize=" + i;
|
|
||||||
return topic ? new ActiveMQTopic(destWithPrefetch) : new ActiveMQQueue(destWithPrefetch);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testOnlyOneSlowConsumerIsAborted() throws Exception {
|
|
||||||
consumerCount = 10;
|
|
||||||
startConsumers(destination);
|
|
||||||
Entry<MessageConsumer, MessageIdList> consumertoAbort = consumers.entrySet().iterator().next();
|
|
||||||
consumertoAbort.getValue().setProcessingDelay(8 * 1000);
|
|
||||||
for (Connection c : connections) {
|
|
||||||
c.setExceptionListener(this);
|
|
||||||
}
|
|
||||||
startProducers(destination, 100);
|
|
||||||
|
|
||||||
allMessagesList.waitForMessagesToArrive(99);
|
|
||||||
allMessagesList.assertAtLeastMessagesReceived(99);
|
|
||||||
|
|
||||||
consumertoAbort.getValue().assertMessagesReceived(1);
|
|
||||||
TimeUnit.SECONDS.sleep(5);
|
|
||||||
consumertoAbort.getValue().assertAtMostMessagesReceived(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAbortAlreadyClosingConsumers() throws Exception {
|
|
||||||
consumerCount = 1;
|
|
||||||
startConsumers(withPrefetch(2, destination));
|
|
||||||
for (MessageIdList list : consumers.values()) {
|
|
||||||
list.setProcessingDelay(6 * 1000);
|
|
||||||
}
|
|
||||||
for (Connection c : connections) {
|
|
||||||
c.setExceptionListener(this);
|
|
||||||
}
|
|
||||||
startProducers(destination, 100);
|
|
||||||
allMessagesList.waitForMessagesToArrive(consumerCount);
|
|
||||||
|
|
||||||
for (MessageConsumer consumer : consumers.keySet()) {
|
|
||||||
LOG.info("closing consumer: " + consumer);
|
|
||||||
/// will block waiting for on message till 6secs expire
|
|
||||||
consumer.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAbortConsumerOnDeadConnection() throws Exception {
|
|
||||||
TransportConnector transportConnector = broker.addConnector("tcp://0.0.0.0:0");
|
|
||||||
transportConnector.setBrokerService(broker);
|
|
||||||
transportConnector.setTaskRunnerFactory(broker.getTaskRunnerFactory());
|
|
||||||
transportConnector.start();
|
|
||||||
SocketProxy socketProxy = new SocketProxy(transportConnector.getPublishableConnectURI());
|
|
||||||
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(socketProxy.getUrl());
|
|
||||||
ActiveMQPrefetchPolicy prefetchPolicy = new ActiveMQPrefetchPolicy();
|
|
||||||
prefetchPolicy.setAll(4);
|
|
||||||
connectionFactory.setPrefetchPolicy(prefetchPolicy);
|
|
||||||
Connection c = connectionFactory.createConnection();
|
|
||||||
connections.add(c);
|
|
||||||
c.start();
|
|
||||||
Session session = c.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
final ActiveMQMessageConsumer messageconsumer = (ActiveMQMessageConsumer) session.createConsumer(destination);
|
|
||||||
startProducers(destination, 10);
|
|
||||||
|
|
||||||
messageconsumer.receive(4000).acknowledge();
|
|
||||||
assertNotNull(messageconsumer.receive(4000));
|
|
||||||
assertNotNull(messageconsumer.receive(4000));
|
|
||||||
assertNotNull(messageconsumer.receive(4000));
|
|
||||||
|
|
||||||
// close control command won't get through
|
|
||||||
socketProxy.pause();
|
|
||||||
|
|
||||||
ActiveMQDestination amqDest = (ActiveMQDestination) destination;
|
|
||||||
ObjectName destinationViewMBean = new ObjectName("org.apache.activemq:destinationType=" +
|
|
||||||
(amqDest.isTopic() ? "Topic" : "Queue") + ",destinationName=" + amqDest.getPhysicalName() + ",type=Broker,brokerName=localhost");
|
|
||||||
|
|
||||||
final DestinationViewMBean destView = (DestinationViewMBean) broker.getManagementContext().newProxyInstance(destinationViewMBean, DestinationViewMBean.class, true);
|
|
||||||
|
|
||||||
assertTrue("Consumer gone from broker view", Wait.waitFor(new Wait.Condition() {
|
|
||||||
@Override
|
|
||||||
public boolean isSatisified() throws Exception {
|
|
||||||
LOG.info("DestView {} consumerCount {}", destView, destView.getConsumerCount());
|
|
||||||
return 0 == destView.getConsumerCount();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
socketProxy.goOn();
|
|
||||||
|
|
||||||
assertTrue("consumer was closed", Wait.waitFor(new Wait.Condition() {
|
|
||||||
@Override
|
|
||||||
public boolean isSatisified() throws Exception {
|
|
||||||
boolean closed = false;
|
|
||||||
try {
|
|
||||||
messageconsumer.receive(400);
|
|
||||||
} catch (javax.jms.IllegalStateException expected) {
|
|
||||||
closed = expected.toString().contains("closed");
|
|
||||||
}
|
|
||||||
return closed;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onException(JMSException exception) {
|
|
||||||
exceptions.add(exception);
|
|
||||||
exception.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,100 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.activemq.util.MessageIdList;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
@RunWith(value = Parameterized.class)
|
|
||||||
public class AbortSlowConsumer1Test extends AbortSlowConsumerBase {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AbortSlowConsumer1Test.class);
|
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "abortConnection({0})-isTopic({1})")
|
|
||||||
public static Collection<Object[]> getTestParameters() {
|
|
||||||
return Arrays.asList(new Object[][]{{Boolean.TRUE, Boolean.TRUE}, {Boolean.TRUE, Boolean.FALSE}, {Boolean.FALSE, Boolean.TRUE}, {Boolean.FALSE, Boolean.FALSE}});
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbortSlowConsumer1Test(Boolean abortConnection, Boolean topic) {
|
|
||||||
this.abortConnection = abortConnection;
|
|
||||||
this.topic = topic;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testSlowConsumerIsAborted() throws Exception {
|
|
||||||
startConsumers(destination);
|
|
||||||
Entry<MessageConsumer, MessageIdList> consumertoAbort = consumers.entrySet().iterator().next();
|
|
||||||
consumertoAbort.getValue().setProcessingDelay(8 * 1000);
|
|
||||||
for (Connection c : connections) {
|
|
||||||
c.setExceptionListener(this);
|
|
||||||
}
|
|
||||||
startProducers(destination, 100);
|
|
||||||
|
|
||||||
consumertoAbort.getValue().assertMessagesReceived(1);
|
|
||||||
TimeUnit.SECONDS.sleep(5);
|
|
||||||
consumertoAbort.getValue().assertAtMostMessagesReceived(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testAbortAlreadyClosedConsumers() throws Exception {
|
|
||||||
Connection conn = createConnectionFactory().createConnection();
|
|
||||||
conn.setExceptionListener(this);
|
|
||||||
connections.add(conn);
|
|
||||||
|
|
||||||
Session sess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
final MessageConsumer consumer = sess.createConsumer(destination);
|
|
||||||
conn.start();
|
|
||||||
startProducers(destination, 20);
|
|
||||||
TimeUnit.SECONDS.sleep(1);
|
|
||||||
LOG.info("closing consumer: " + consumer);
|
|
||||||
consumer.close();
|
|
||||||
|
|
||||||
TimeUnit.SECONDS.sleep(5);
|
|
||||||
assertTrue("no exceptions : " + exceptions, exceptions.isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testAbortAlreadyClosedConnection() throws Exception {
|
|
||||||
Connection conn = createConnectionFactory().createConnection();
|
|
||||||
conn.setExceptionListener(this);
|
|
||||||
|
|
||||||
Session sess = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
sess.createConsumer(destination);
|
|
||||||
conn.start();
|
|
||||||
startProducers(destination, 20);
|
|
||||||
TimeUnit.SECONDS.sleep(1);
|
|
||||||
LOG.info("closing connection: " + conn);
|
|
||||||
conn.close();
|
|
||||||
|
|
||||||
TimeUnit.SECONDS.sleep(5);
|
|
||||||
assertTrue("no exceptions : " + exceptions, exceptions.isEmpty());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,54 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import org.apache.activemq.util.MessageIdList;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
|
|
||||||
@RunWith(value = Parameterized.class)
|
|
||||||
public class AbortSlowConsumer2Test extends AbortSlowConsumerBase {
|
|
||||||
|
|
||||||
@Parameterized.Parameters(name = "isTopic({0})")
|
|
||||||
public static Collection<Object[]> getTestParameters() {
|
|
||||||
return Arrays.asList(new Object[][]{{Boolean.TRUE}, {Boolean.FALSE}});
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbortSlowConsumer2Test(Boolean isTopic) {
|
|
||||||
this.topic = isTopic;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testLittleSlowConsumerIsNotAborted() throws Exception {
|
|
||||||
startConsumers(destination);
|
|
||||||
Entry<MessageConsumer, MessageIdList> consumertoAbort = consumers.entrySet().iterator().next();
|
|
||||||
consumertoAbort.getValue().setProcessingDelay(500);
|
|
||||||
for (Connection c : connections) {
|
|
||||||
c.setExceptionListener(this);
|
|
||||||
}
|
|
||||||
startProducers(destination, 12);
|
|
||||||
allMessagesList.waitForMessagesToArrive(10);
|
|
||||||
allMessagesList.assertAtLeastMessagesReceived(10);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,80 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.ExceptionListener;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.activemq.JmsMultipleClientsTestSupport;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.policy.AbortSlowConsumerStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class AbortSlowConsumerBase extends JmsMultipleClientsTestSupport implements ExceptionListener {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AbortSlowConsumerBase.class);
|
|
||||||
|
|
||||||
protected AbortSlowConsumerStrategy underTest;
|
|
||||||
protected boolean abortConnection = false;
|
|
||||||
protected long checkPeriod = 2 * 1000;
|
|
||||||
protected long maxSlowDuration = 5 * 1000;
|
|
||||||
protected final List<Throwable> exceptions = new ArrayList<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
exceptions.clear();
|
|
||||||
topic = true;
|
|
||||||
underTest = createSlowConsumerStrategy();
|
|
||||||
super.setUp();
|
|
||||||
createDestination();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AbortSlowConsumerStrategy createSlowConsumerStrategy() {
|
|
||||||
return new AbortSlowConsumerStrategy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
underTest.setAbortConnection(abortConnection);
|
|
||||||
underTest.setCheckPeriod(checkPeriod);
|
|
||||||
underTest.setMaxSlowDuration(maxSlowDuration);
|
|
||||||
|
|
||||||
policy.setSlowConsumerStrategy(underTest);
|
|
||||||
policy.setQueuePrefetch(10);
|
|
||||||
policy.setTopicPrefetch(10);
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
broker.setDestinationPolicy(pMap);
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onException(JMSException exception) {
|
|
||||||
exceptions.add(exception);
|
|
||||||
exception.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,99 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.Message;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.RedeliveryPolicy;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DeadLetterTest extends DeadLetterTestSupport {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DeadLetterTest.class);
|
|
||||||
|
|
||||||
protected int rollbackCount;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doTest() throws Exception {
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
ActiveMQConnection amqConnection = (ActiveMQConnection) connection;
|
|
||||||
rollbackCount = amqConnection.getRedeliveryPolicy().getMaximumRedeliveries() + 1;
|
|
||||||
LOG.info("Will redeliver messages: " + rollbackCount + " times");
|
|
||||||
|
|
||||||
makeConsumer();
|
|
||||||
makeDlqConsumer();
|
|
||||||
|
|
||||||
sendMessages();
|
|
||||||
|
|
||||||
// now lets receive and rollback N times
|
|
||||||
for (int i = 0; i < messageCount; i++) {
|
|
||||||
consumeAndRollback(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < messageCount; i++) {
|
|
||||||
Message msg = dlqConsumer.receive(1000);
|
|
||||||
assertMessage(msg, i);
|
|
||||||
assertNotNull("Should be a DLQ message for loop: " + i, msg);
|
|
||||||
}
|
|
||||||
session.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void consumeAndRollback(int messageCounter) throws Exception {
|
|
||||||
for (int i = 0; i < rollbackCount; i++) {
|
|
||||||
Message message = consumer.receive(5000);
|
|
||||||
assertNotNull("No message received for message: " + messageCounter + " and rollback loop: " + i, message);
|
|
||||||
assertMessage(message, messageCounter);
|
|
||||||
|
|
||||||
session.rollback();
|
|
||||||
}
|
|
||||||
LOG.info("Rolled back: " + rollbackCount + " times");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
transactedMode = true;
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
ActiveMQConnectionFactory answer = super.createConnectionFactory();
|
|
||||||
RedeliveryPolicy policy = new RedeliveryPolicy();
|
|
||||||
policy.setMaximumRedeliveries(3);
|
|
||||||
policy.setBackOffMultiplier((short) 1);
|
|
||||||
policy.setInitialRedeliveryDelay(10);
|
|
||||||
policy.setUseExponentialBackOff(false);
|
|
||||||
answer.setRedeliveryPolicy(policy);
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Destination createDlqDestination() {
|
|
||||||
return new ActiveMQQueue("ActiveMQ.DLQ");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,213 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.DeliveryMode;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Queue;
|
|
||||||
import javax.jms.QueueBrowser;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TextMessage;
|
|
||||||
import javax.jms.Topic;
|
|
||||||
|
|
||||||
import org.apache.activemq.TestSupport;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.DestinationStatistics;
|
|
||||||
import org.apache.activemq.broker.region.RegionBroker;
|
|
||||||
import org.apache.activemq.broker.region.policy.DeadLetterStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public abstract class DeadLetterTestSupport extends TestSupport {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DeadLetterTestSupport.class);
|
|
||||||
|
|
||||||
protected int messageCount = 10;
|
|
||||||
protected long timeToLive;
|
|
||||||
protected Connection connection;
|
|
||||||
protected Session session;
|
|
||||||
protected MessageConsumer consumer;
|
|
||||||
protected MessageProducer producer;
|
|
||||||
protected int deliveryMode = DeliveryMode.PERSISTENT;
|
|
||||||
protected boolean durableSubscriber;
|
|
||||||
protected Destination dlqDestination;
|
|
||||||
protected MessageConsumer dlqConsumer;
|
|
||||||
protected QueueBrowser dlqBrowser;
|
|
||||||
protected BrokerService broker;
|
|
||||||
protected boolean transactedMode;
|
|
||||||
protected int acknowledgeMode = Session.CLIENT_ACKNOWLEDGE;
|
|
||||||
private Destination destination;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
broker = createBroker();
|
|
||||||
broker.start();
|
|
||||||
connection = createConnection();
|
|
||||||
connection.setClientID(createClientId());
|
|
||||||
|
|
||||||
session = connection.createSession(transactedMode, acknowledgeMode);
|
|
||||||
connection.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String createClientId() {
|
|
||||||
return toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
if (connection != null) {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
if (broker != null) {
|
|
||||||
broker.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void doTest() throws Exception;
|
|
||||||
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = new BrokerService();
|
|
||||||
broker.setPersistent(false);
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
DeadLetterStrategy defaultDeadLetterStrategy = policy.getDeadLetterStrategy();
|
|
||||||
if (defaultDeadLetterStrategy != null) {
|
|
||||||
defaultDeadLetterStrategy.setProcessNonPersistent(true);
|
|
||||||
}
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
broker.setDestinationPolicy(pMap);
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void makeConsumer() throws JMSException {
|
|
||||||
Destination destination = getDestination();
|
|
||||||
LOG.info("Consuming from: " + destination);
|
|
||||||
if (durableSubscriber) {
|
|
||||||
consumer = session.createDurableSubscriber((Topic) destination, destination.toString());
|
|
||||||
} else {
|
|
||||||
consumer = session.createConsumer(destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void makeDlqConsumer() throws Exception {
|
|
||||||
dlqDestination = createDlqDestination();
|
|
||||||
|
|
||||||
LOG.info("Consuming from dead letter on: " + dlqDestination);
|
|
||||||
dlqConsumer = session.createConsumer(dlqDestination);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void makeDlqBrowser() throws JMSException {
|
|
||||||
dlqDestination = createDlqDestination();
|
|
||||||
|
|
||||||
LOG.info("Browsing dead letter on: " + dlqDestination);
|
|
||||||
dlqBrowser = session.createBrowser((Queue) dlqDestination);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void sendMessages() throws JMSException {
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
producer = session.createProducer(getDestination());
|
|
||||||
producer.setDeliveryMode(deliveryMode);
|
|
||||||
producer.setTimeToLive(timeToLive);
|
|
||||||
|
|
||||||
LOG.info("Sending " + messageCount + " messages to: " + getDestination());
|
|
||||||
for (int i = 0; i < messageCount; i++) {
|
|
||||||
Message message = createMessage(session, i);
|
|
||||||
producer.send(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected TextMessage createMessage(Session session, int i) throws JMSException {
|
|
||||||
return session.createTextMessage(getMessageText(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getMessageText(int i) {
|
|
||||||
return "message: " + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void assertMessage(Message message, int i) throws Exception {
|
|
||||||
LOG.info("Received message: " + message);
|
|
||||||
assertNotNull("No message received for index: " + i, message);
|
|
||||||
assertTrue("Should be a TextMessage not: " + message, message instanceof TextMessage);
|
|
||||||
TextMessage textMessage = (TextMessage) message;
|
|
||||||
assertEquals("text of message: " + i, getMessageText(i), textMessage.getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Destination createDlqDestination();
|
|
||||||
|
|
||||||
public void testTransientTopicMessage() throws Exception {
|
|
||||||
super.topic = true;
|
|
||||||
deliveryMode = DeliveryMode.NON_PERSISTENT;
|
|
||||||
durableSubscriber = true;
|
|
||||||
doTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDurableTopicMessage() throws Exception {
|
|
||||||
super.topic = true;
|
|
||||||
deliveryMode = DeliveryMode.PERSISTENT;
|
|
||||||
durableSubscriber = true;
|
|
||||||
doTest();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testTransientQueueMessage() throws Exception {
|
|
||||||
super.topic = false;
|
|
||||||
deliveryMode = DeliveryMode.NON_PERSISTENT;
|
|
||||||
durableSubscriber = false;
|
|
||||||
doTest();
|
|
||||||
validateConsumerPrefetch(this.getDestinationString(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDurableQueueMessage() throws Exception {
|
|
||||||
super.topic = false;
|
|
||||||
deliveryMode = DeliveryMode.PERSISTENT;
|
|
||||||
durableSubscriber = false;
|
|
||||||
doTest();
|
|
||||||
validateConsumerPrefetch(this.getDestinationString(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Destination getDestination() {
|
|
||||||
if (destination == null) {
|
|
||||||
destination = createDestination();
|
|
||||||
}
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateConsumerPrefetch(String destination, long expectedCount) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(100);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
}
|
|
||||||
RegionBroker regionBroker = (RegionBroker) broker.getRegionBroker();
|
|
||||||
for (org.apache.activemq.broker.region.Destination dest : regionBroker.getQueueRegion().getDestinationMap().values()) {
|
|
||||||
if (dest.getName().equals(destination)) {
|
|
||||||
DestinationStatistics stats = dest.getDestinationStatistics();
|
|
||||||
LOG.info(">>>> inflight for : " + dest.getName() + ": " + stats.getInflight().getCount());
|
|
||||||
assertEquals("inflight for: " + dest.getName() + ": " + stats.getInflight().getCount() + " matches", expectedCount, stats.getInflight().getCount());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,75 +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.broker.policy;
|
|
||||||
|
|
||||||
import org.apache.activemq.TestSupport;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.policy.PendingQueueMessageStoragePolicy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PendingSubscriberMessageStoragePolicy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.VMPendingQueueMessageStoragePolicy;
|
|
||||||
import org.apache.activemq.broker.region.policy.VMPendingSubscriberMessageStoragePolicy;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.xbean.BrokerFactoryBean;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DestinationCursorConfigTest extends TestSupport {
|
|
||||||
|
|
||||||
protected BrokerService broker;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
broker = createBroker();
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
broker.stop();
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerFactoryBean factory = new BrokerFactoryBean(new ClassPathResource("org/apache/activemq/broker/policy/cursor.xml"));
|
|
||||||
factory.afterPropertiesSet();
|
|
||||||
BrokerService answer = factory.getBroker();
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testQueueConfiguration() throws Exception {
|
|
||||||
super.topic = false;
|
|
||||||
ActiveMQDestination destination = (ActiveMQDestination) createDestination("org.apache.foo");
|
|
||||||
PolicyEntry entry = broker.getDestinationPolicy().getEntryFor(destination);
|
|
||||||
PendingQueueMessageStoragePolicy policy = entry.getPendingQueuePolicy();
|
|
||||||
assertNotNull(policy);
|
|
||||||
assertTrue("Policy is: " + policy, policy instanceof VMPendingQueueMessageStoragePolicy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testTopicConfiguration() throws Exception {
|
|
||||||
super.topic = true;
|
|
||||||
ActiveMQDestination destination = (ActiveMQDestination) createDestination("org.apache.foo");
|
|
||||||
PolicyEntry entry = broker.getDestinationPolicy().getEntryFor(destination);
|
|
||||||
PendingSubscriberMessageStoragePolicy policy = entry.getPendingSubscriberPolicy();
|
|
||||||
assertNotNull(policy);
|
|
||||||
assertFalse(entry.isProducerFlowControl());
|
|
||||||
assertTrue(entry.getMemoryLimit() == (1024 * 1024));
|
|
||||||
assertTrue("subscriberPolicy is: " + policy, policy instanceof VMPendingSubscriberMessageStoragePolicy);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.Message;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.policy.DeadLetterStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.DiscardingDeadLetterStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DiscardingDeadLetterPolicyTest extends DeadLetterTest {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DiscardingDeadLetterPolicyTest.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
DeadLetterStrategy strategy = new DiscardingDeadLetterStrategy();
|
|
||||||
strategy.setProcessNonPersistent(true);
|
|
||||||
policy.setDeadLetterStrategy(strategy);
|
|
||||||
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
|
|
||||||
broker.setDestinationPolicy(pMap);
|
|
||||||
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doTest() throws Exception {
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
ActiveMQConnection amqConnection = (ActiveMQConnection) connection;
|
|
||||||
rollbackCount = amqConnection.getRedeliveryPolicy().getMaximumRedeliveries() + 1;
|
|
||||||
LOG.info("Will redeliver messages: " + rollbackCount + " times");
|
|
||||||
|
|
||||||
makeConsumer();
|
|
||||||
makeDlqConsumer();
|
|
||||||
|
|
||||||
sendMessages();
|
|
||||||
|
|
||||||
// now lets receive and rollback N times
|
|
||||||
for (int i = 0; i < messageCount; i++) {
|
|
||||||
consumeAndRollback(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < messageCount; i++) {
|
|
||||||
Message msg = dlqConsumer.receive(1000);
|
|
||||||
assertNull("Should not be a DLQ message for loop: " + i, msg);
|
|
||||||
}
|
|
||||||
session.commit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,109 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.DeliveryMode;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.Queue;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.policy.DeadLetterStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.IndividualDeadLetterStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class IndividualDeadLetterTest extends DeadLetterTest {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(IndividualDeadLetterTest.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
DeadLetterStrategy strategy = new IndividualDeadLetterStrategy();
|
|
||||||
strategy.setProcessNonPersistent(true);
|
|
||||||
policy.setDeadLetterStrategy(strategy);
|
|
||||||
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
|
|
||||||
broker.setDestinationPolicy(pMap);
|
|
||||||
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Destination createDlqDestination() {
|
|
||||||
String prefix = topic ? "ActiveMQ.DLQ.Topic." : "ActiveMQ.DLQ.Queue.";
|
|
||||||
return new ActiveMQQueue(prefix + getClass().getName() + "." + getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDLQBrowsing() throws Exception {
|
|
||||||
super.topic = false;
|
|
||||||
deliveryMode = DeliveryMode.PERSISTENT;
|
|
||||||
durableSubscriber = false;
|
|
||||||
messageCount = 1;
|
|
||||||
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
ActiveMQConnection amqConnection = (ActiveMQConnection) connection;
|
|
||||||
rollbackCount = amqConnection.getRedeliveryPolicy().getMaximumRedeliveries() + 1;
|
|
||||||
LOG.info("Will redeliver messages: " + rollbackCount + " times");
|
|
||||||
|
|
||||||
sendMessages();
|
|
||||||
|
|
||||||
// now lets receive and rollback N times
|
|
||||||
for (int i = 0; i < rollbackCount; i++) {
|
|
||||||
makeConsumer();
|
|
||||||
Message message = consumer.receive(5000);
|
|
||||||
assertNotNull("No message received: ", message);
|
|
||||||
|
|
||||||
session.rollback();
|
|
||||||
LOG.info("Rolled back: " + rollbackCount + " times");
|
|
||||||
consumer.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
makeDlqBrowser();
|
|
||||||
browseDlq();
|
|
||||||
dlqBrowser.close();
|
|
||||||
session.close();
|
|
||||||
Thread.sleep(1000);
|
|
||||||
session = connection.createSession(transactedMode, acknowledgeMode);
|
|
||||||
Queue testQueue = new ActiveMQQueue("ActiveMQ.DLQ.Queue.ActiveMQ.DLQ.Queue." + getClass().getName() + "." + getName());
|
|
||||||
MessageConsumer testConsumer = session.createConsumer(testQueue);
|
|
||||||
assertNull("The message shouldn't be sent to another DLQ", testConsumer.receive(1000));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void browseDlq() throws Exception {
|
|
||||||
Enumeration<?> messages = dlqBrowser.getEnumeration();
|
|
||||||
while (messages.hasMoreElements()) {
|
|
||||||
LOG.info("Browsing: " + messages.nextElement());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.Destination;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.xbean.BrokerFactoryBean;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class IndividualDeadLetterViaXmlTest extends DeadLetterTest {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(IndividualDeadLetterViaXmlTest.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerFactoryBean factory = new BrokerFactoryBean(new ClassPathResource("org/apache/activemq/broker/policy/individual-dlq.xml"));
|
|
||||||
factory.afterPropertiesSet();
|
|
||||||
BrokerService answer = factory.getBroker();
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Destination createDlqDestination() {
|
|
||||||
String queueName = "Test.DLQ." + getClass().getName() + "." + getName();
|
|
||||||
LOG.info("Using queue name: " + queueName);
|
|
||||||
return new ActiveMQQueue(queueName);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +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.broker.policy;
|
|
||||||
|
|
||||||
import org.apache.activemq.TestSupport;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.Queue;
|
|
||||||
import org.apache.activemq.broker.region.group.CachedMessageGroupMap;
|
|
||||||
import org.apache.activemq.broker.region.group.MessageGroupHashBucket;
|
|
||||||
import org.apache.activemq.broker.region.group.MessageGroupMap;
|
|
||||||
import org.apache.activemq.broker.region.group.SimpleMessageGroupMap;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class MessageGroupConfigTest extends TestSupport {
|
|
||||||
|
|
||||||
protected BrokerService broker;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
broker.stop();
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCachedGroupConfiguration() throws Exception {
|
|
||||||
doTestGroupConfiguration("cached", CachedMessageGroupMap.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCachedGroupConfigurationWithCacheSize() throws Exception {
|
|
||||||
CachedMessageGroupMap result = (CachedMessageGroupMap) doTestGroupConfiguration("cached?cacheSize=10", CachedMessageGroupMap.class);
|
|
||||||
assertEquals(10, result.getMaximumCacheSize());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSimpleGroupConfiguration() throws Exception {
|
|
||||||
doTestGroupConfiguration("simple", SimpleMessageGroupMap.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testBucketGroupConfiguration() throws Exception {
|
|
||||||
doTestGroupConfiguration("bucket", MessageGroupHashBucket.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testBucketGroupConfigurationWithBucketCount() throws Exception {
|
|
||||||
MessageGroupHashBucket result = (MessageGroupHashBucket) doTestGroupConfiguration("bucket?bucketCount=2", MessageGroupHashBucket.class);
|
|
||||||
assertEquals(2, result.getBucketCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
public MessageGroupMap doTestGroupConfiguration(String type, Class classType) throws Exception {
|
|
||||||
broker = new BrokerService();
|
|
||||||
|
|
||||||
PolicyEntry defaultEntry = new PolicyEntry();
|
|
||||||
defaultEntry.setMessageGroupMapFactoryType(type);
|
|
||||||
PolicyMap policyMap = new PolicyMap();
|
|
||||||
policyMap.setDefaultEntry(defaultEntry);
|
|
||||||
broker.setDestinationPolicy(policyMap);
|
|
||||||
broker.start();
|
|
||||||
super.topic = false;
|
|
||||||
ActiveMQDestination destination = (ActiveMQDestination) createDestination("org.apache.foo");
|
|
||||||
Queue brokerDestination = (Queue) broker.getDestination(destination);
|
|
||||||
|
|
||||||
assertNotNull(brokerDestination);
|
|
||||||
MessageGroupMap messageGroupMap = brokerDestination.getMessageGroupOwners();
|
|
||||||
assertNotNull(messageGroupMap);
|
|
||||||
assertTrue(messageGroupMap.getClass().isAssignableFrom(classType));
|
|
||||||
return messageGroupMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,153 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageListener;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnection;
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.RedeliveryPolicy;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class MessageListenerDeadLetterTest extends DeadLetterTestSupport {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(MessageListenerDeadLetterTest.class);
|
|
||||||
|
|
||||||
private int rollbackCount;
|
|
||||||
|
|
||||||
private Session dlqSession;
|
|
||||||
|
|
||||||
private final Error[] error = new Error[1];
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doTest() throws Exception {
|
|
||||||
messageCount = 200;
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
ActiveMQConnection amqConnection = (ActiveMQConnection) connection;
|
|
||||||
rollbackCount = amqConnection.getRedeliveryPolicy().getMaximumRedeliveries() + 1;
|
|
||||||
LOG.info("Will redeliver messages: " + rollbackCount + " times");
|
|
||||||
|
|
||||||
makeConsumer();
|
|
||||||
makeDlqConsumer();
|
|
||||||
|
|
||||||
sendMessages();
|
|
||||||
|
|
||||||
// now lets receive and rollback N times
|
|
||||||
int maxRollbacks = messageCount * rollbackCount;
|
|
||||||
consumer.setMessageListener(new RollbackMessageListener(maxRollbacks, rollbackCount));
|
|
||||||
|
|
||||||
for (int i = 0; i < messageCount; i++) {
|
|
||||||
Message msg = dlqConsumer.receive(4000);
|
|
||||||
if (error[0] != null) {
|
|
||||||
// error from message listener
|
|
||||||
throw error[0];
|
|
||||||
}
|
|
||||||
assertMessage(msg, i);
|
|
||||||
assertNotNull("Should be a DLQ message for loop: " + i, msg);
|
|
||||||
}
|
|
||||||
if (error[0] != null) {
|
|
||||||
throw error[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void makeDlqConsumer() throws JMSException {
|
|
||||||
dlqDestination = createDlqDestination();
|
|
||||||
|
|
||||||
LOG.info("Consuming from dead letter on: " + dlqDestination);
|
|
||||||
dlqConsumer = dlqSession.createConsumer(dlqDestination);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
transactedMode = true;
|
|
||||||
super.setUp();
|
|
||||||
dlqSession = connection.createSession(transactedMode, acknowledgeMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
dlqConsumer.close();
|
|
||||||
dlqSession.close();
|
|
||||||
session.close();
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
ActiveMQConnectionFactory answer = super.createConnectionFactory();
|
|
||||||
RedeliveryPolicy policy = new RedeliveryPolicy();
|
|
||||||
policy.setMaximumRedeliveries(3);
|
|
||||||
policy.setBackOffMultiplier((short) 1);
|
|
||||||
policy.setRedeliveryDelay(0);
|
|
||||||
policy.setInitialRedeliveryDelay(0);
|
|
||||||
policy.setUseExponentialBackOff(false);
|
|
||||||
answer.setRedeliveryPolicy(policy);
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Destination createDlqDestination() {
|
|
||||||
return new ActiveMQQueue("ActiveMQ.DLQ");
|
|
||||||
}
|
|
||||||
|
|
||||||
class RollbackMessageListener implements MessageListener {
|
|
||||||
|
|
||||||
final int maxRollbacks;
|
|
||||||
|
|
||||||
final int deliveryCount;
|
|
||||||
|
|
||||||
AtomicInteger rollbacks = new AtomicInteger();
|
|
||||||
|
|
||||||
RollbackMessageListener(int c, int delvery) {
|
|
||||||
maxRollbacks = c;
|
|
||||||
deliveryCount = delvery;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessage(Message message) {
|
|
||||||
try {
|
|
||||||
int expectedMessageId = rollbacks.get() / deliveryCount;
|
|
||||||
LOG.info("expecting messageId: " + expectedMessageId);
|
|
||||||
assertMessage(message, expectedMessageId);
|
|
||||||
if (rollbacks.incrementAndGet() > maxRollbacks) {
|
|
||||||
fail("received too many messages, already done too many rollbacks: " + rollbacks);
|
|
||||||
}
|
|
||||||
session.rollback();
|
|
||||||
|
|
||||||
} catch (Throwable e) {
|
|
||||||
LOG.error("unexpected exception:" + e, e);
|
|
||||||
// propagating assertError to execution task will cause a hang
|
|
||||||
// at shutdown
|
|
||||||
if (e instanceof Error) {
|
|
||||||
error[0] = (Error) e;
|
|
||||||
} else {
|
|
||||||
fail("unexpected exception: " + e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,116 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.DeliveryMode;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TextMessage;
|
|
||||||
import javax.jms.Topic;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.advisory.AdvisorySupport;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class NoConsumerDeadLetterTest extends DeadLetterTestSupport {
|
|
||||||
|
|
||||||
// lets disable the inapplicable tests
|
|
||||||
@Override
|
|
||||||
public void testDurableQueueMessage() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testDurableTopicMessage() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doTest() throws Exception {
|
|
||||||
makeDlqConsumer();
|
|
||||||
sendMessages();
|
|
||||||
|
|
||||||
for (int i = 0; i < messageCount; i++) {
|
|
||||||
Message msg = dlqConsumer.receive(1000);
|
|
||||||
assertNotNull("Should be a message for loop: " + i, msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testConsumerReceivesMessages() throws Exception {
|
|
||||||
this.topic = false;
|
|
||||||
ActiveMQConnectionFactory factory = createConnectionFactory();
|
|
||||||
connection = factory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageProducer producer = session.createProducer(getDestination());
|
|
||||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
|
||||||
|
|
||||||
Topic advisoryTopic = AdvisorySupport.getNoQueueConsumersAdvisoryTopic(getDestination());
|
|
||||||
MessageConsumer advisoryConsumer = session.createConsumer(advisoryTopic);
|
|
||||||
|
|
||||||
TextMessage msg = session.createTextMessage("Message: x");
|
|
||||||
producer.send(msg);
|
|
||||||
|
|
||||||
Message advisoryMessage = advisoryConsumer.receive(1000);
|
|
||||||
assertNotNull("Advisory message not received", advisoryMessage);
|
|
||||||
|
|
||||||
Thread.sleep(1000);
|
|
||||||
|
|
||||||
factory = createConnectionFactory();
|
|
||||||
connection = factory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
|
|
||||||
MessageConsumer consumer = session.createConsumer(getDestination());
|
|
||||||
Message received = consumer.receive(1000);
|
|
||||||
assertNotNull("Message not received", received);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
policy.setSendAdvisoryIfNoConsumers(true);
|
|
||||||
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
|
|
||||||
broker.setDestinationPolicy(pMap);
|
|
||||||
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Destination createDlqDestination() {
|
|
||||||
if (this.topic) {
|
|
||||||
return AdvisorySupport.getNoTopicConsumersAdvisoryTopic((ActiveMQDestination) getDestination());
|
|
||||||
} else {
|
|
||||||
return AdvisorySupport.getNoQueueConsumersAdvisoryTopic((ActiveMQDestination) getDestination());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,33 +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.broker.policy;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.RedeliveryPolicy;
|
|
||||||
|
|
||||||
public class NoRetryDeadLetterTest extends DeadLetterTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
|
||||||
ActiveMQConnectionFactory connectionFactory = super.createConnectionFactory();
|
|
||||||
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
|
|
||||||
redeliveryPolicy.setMaximumRedeliveries(0);
|
|
||||||
connectionFactory.setRedeliveryPolicy(redeliveryPolicy);
|
|
||||||
return connectionFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,70 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.Destination;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.policy.IndividualDeadLetterStrategy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* for durable subs, allow a dlq per subscriber such that poison messages are not duplicates
|
|
||||||
* on the dlq and such that rejecting consumers can be identified
|
|
||||||
* https://issues.apache.org/jira/browse/AMQ-3003
|
|
||||||
*/
|
|
||||||
public class PerDurableConsumerDeadLetterTest extends DeadLetterTest {
|
|
||||||
|
|
||||||
private static final String CLIENT_ID = "george";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
IndividualDeadLetterStrategy strategy = new IndividualDeadLetterStrategy();
|
|
||||||
strategy.setProcessNonPersistent(true);
|
|
||||||
strategy.setDestinationPerDurableSubscriber(true);
|
|
||||||
policy.setDeadLetterStrategy(strategy);
|
|
||||||
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
|
|
||||||
broker.setDestinationPolicy(pMap);
|
|
||||||
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String createClientId() {
|
|
||||||
return CLIENT_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Destination createDlqDestination() {
|
|
||||||
String prefix = topic ? "ActiveMQ.DLQ.Topic." : "ActiveMQ.DLQ.Queue.";
|
|
||||||
String destinationName = prefix + getClass().getName() + "." + getName();
|
|
||||||
if (durableSubscriber) {
|
|
||||||
String subName = // connectionId:SubName
|
|
||||||
CLIENT_ID + ":" + getDestination().toString();
|
|
||||||
destinationName += "." + subName;
|
|
||||||
}
|
|
||||||
return new ActiveMQQueue(destinationName);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,81 +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.broker.policy;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
|
||||||
import org.apache.activemq.broker.region.Subscription;
|
|
||||||
import org.apache.activemq.broker.region.TopicSubscription;
|
|
||||||
import org.apache.activemq.broker.region.policy.PriorityNetworkDispatchPolicy;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQMessage;
|
|
||||||
import org.apache.activemq.command.ConsumerId;
|
|
||||||
import org.apache.activemq.command.ConsumerInfo;
|
|
||||||
import org.apache.activemq.command.MessageId;
|
|
||||||
import org.apache.activemq.usage.SystemUsage;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
public class PriorityNetworkDispatchPolicyTest {
|
|
||||||
|
|
||||||
PriorityNetworkDispatchPolicy underTest = new PriorityNetworkDispatchPolicy();
|
|
||||||
SystemUsage usageManager = new SystemUsage();
|
|
||||||
ConsumerInfo info = new ConsumerInfo();
|
|
||||||
ActiveMQMessage node = new ActiveMQMessage();
|
|
||||||
ConsumerId id = new ConsumerId();
|
|
||||||
ConnectionContext context = new ConnectionContext();
|
|
||||||
BrokerService brokerService = new BrokerService();
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void init() throws Exception {
|
|
||||||
info.setDestination(ActiveMQDestination.createDestination("test", ActiveMQDestination.TOPIC_TYPE));
|
|
||||||
info.setConsumerId(id);
|
|
||||||
info.setNetworkSubscription(true);
|
|
||||||
info.setNetworkConsumerPath(new ConsumerId[]{id});
|
|
||||||
node.setMessageId(new MessageId("test:1:1:1:1"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void stopBroker() throws Exception {
|
|
||||||
brokerService.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRemoveLowerPriorityDup() throws Exception {
|
|
||||||
|
|
||||||
List<Subscription> consumers = new ArrayList<>();
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
ConsumerInfo instance = info.copy();
|
|
||||||
instance.setPriority((byte) i);
|
|
||||||
consumers.add(new TopicSubscription(brokerService.getBroker(), context, instance, usageManager));
|
|
||||||
}
|
|
||||||
underTest.dispatch(node, null, consumers);
|
|
||||||
|
|
||||||
long count = 0;
|
|
||||||
for (Subscription consumer : consumers) {
|
|
||||||
count += consumer.getEnqueueCounter();
|
|
||||||
}
|
|
||||||
assertEquals("only one sub got message", 1, count);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,135 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.Session;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.QueueSubscriptionTest;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.broker.region.policy.RoundRobinDispatchPolicy;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
|
||||||
|
|
||||||
@RunWith(BlockJUnit4ClassRunner.class)
|
|
||||||
public class RoundRobinDispatchPolicyTest extends QueueSubscriptionTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
policy.setDispatchPolicy(new RoundRobinDispatchPolicy());
|
|
||||||
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
|
|
||||||
broker.setDestinationPolicy(pMap);
|
|
||||||
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersSmallMessagesOnePrefetch() throws Exception {
|
|
||||||
super.testOneProducerTwoConsumersSmallMessagesOnePrefetch();
|
|
||||||
|
|
||||||
// Ensure that each consumer should have received at least one message
|
|
||||||
// We cannot guarantee that messages will be equally divided, since
|
|
||||||
// prefetch is one
|
|
||||||
assertEachConsumerReceivedAtLeastXMessages(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersSmallMessagesLargePrefetch() throws Exception {
|
|
||||||
super.testOneProducerTwoConsumersSmallMessagesLargePrefetch();
|
|
||||||
assertMessagesDividedAmongConsumers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersLargeMessagesOnePrefetch() throws Exception {
|
|
||||||
super.testOneProducerTwoConsumersLargeMessagesOnePrefetch();
|
|
||||||
|
|
||||||
// Ensure that each consumer should have received at least one message
|
|
||||||
// We cannot guarantee that messages will be equally divided, since
|
|
||||||
// prefetch is one
|
|
||||||
assertEachConsumerReceivedAtLeastXMessages(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersLargeMessagesLargePrefetch() throws Exception {
|
|
||||||
super.testOneProducerTwoConsumersLargeMessagesLargePrefetch();
|
|
||||||
assertMessagesDividedAmongConsumers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerManyConsumersFewMessages() throws Exception {
|
|
||||||
super.testOneProducerManyConsumersFewMessages();
|
|
||||||
|
|
||||||
// Since there are more consumers, each consumer should have received at
|
|
||||||
// most one message only
|
|
||||||
assertMessagesDividedAmongConsumers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerManyConsumersManyMessages() throws Exception {
|
|
||||||
super.testOneProducerManyConsumersManyMessages();
|
|
||||||
assertMessagesDividedAmongConsumers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testManyProducersManyConsumers() throws Exception {
|
|
||||||
super.testManyProducersManyConsumers();
|
|
||||||
assertMessagesDividedAmongConsumers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoMatchingConsumersOneNotMatchingConsumer() throws Exception {
|
|
||||||
// Create consumer that won't consume any message
|
|
||||||
createMessageConsumer(createConnectionFactory().createConnection(), createDestination(), "JMSPriority<1");
|
|
||||||
super.testOneProducerTwoConsumersSmallMessagesLargePrefetch();
|
|
||||||
assertMessagesDividedAmongConsumers();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MessageConsumer createMessageConsumer(Connection conn,
|
|
||||||
Destination dest,
|
|
||||||
String selector) throws Exception {
|
|
||||||
connections.add(conn);
|
|
||||||
|
|
||||||
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
final MessageConsumer consumer = sess.createConsumer(dest, selector);
|
|
||||||
conn.start();
|
|
||||||
|
|
||||||
return consumer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void assertMessagesDividedAmongConsumers() {
|
|
||||||
assertEachConsumerReceivedAtLeastXMessages((messageCount * producerCount) / consumerCount);
|
|
||||||
assertEachConsumerReceivedAtMostXMessages(((messageCount * producerCount) / consumerCount) + 1);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,139 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Destination;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.Session;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerPlugin;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ActiveMQTopic;
|
|
||||||
import org.apache.activemq.filter.DestinationMap;
|
|
||||||
import org.apache.activemq.security.AuthorizationMap;
|
|
||||||
import org.apache.activemq.security.AuthorizationPlugin;
|
|
||||||
import org.apache.activemq.security.DefaultAuthorizationMap;
|
|
||||||
import org.apache.activemq.security.SimpleAuthorizationMap;
|
|
||||||
import org.apache.activemq.security.SimpleSecurityBrokerSystemTest;
|
|
||||||
|
|
||||||
import static org.apache.activemq.security.SimpleSecurityBrokerSystemTest.ADMINS;
|
|
||||||
import static org.apache.activemq.security.SimpleSecurityBrokerSystemTest.USERS;
|
|
||||||
import static org.apache.activemq.security.SimpleSecurityBrokerSystemTest.WILDCARD;
|
|
||||||
|
|
||||||
public class SecureDLQTest extends DeadLetterTestSupport {
|
|
||||||
|
|
||||||
Connection dlqConnection;
|
|
||||||
Session dlqSession;
|
|
||||||
|
|
||||||
public static AuthorizationMap createAuthorizationMap() {
|
|
||||||
DestinationMap readAccess = new DefaultAuthorizationMap();
|
|
||||||
readAccess.put(new ActiveMQQueue("TEST"), ADMINS);
|
|
||||||
readAccess.put(new ActiveMQQueue("TEST"), USERS);
|
|
||||||
readAccess.put(new ActiveMQQueue("ActiveMQ.DLQ"), ADMINS);
|
|
||||||
|
|
||||||
DestinationMap writeAccess = new DefaultAuthorizationMap();
|
|
||||||
writeAccess.put(new ActiveMQQueue("TEST"), ADMINS);
|
|
||||||
writeAccess.put(new ActiveMQQueue("TEST"), USERS);
|
|
||||||
writeAccess.put(new ActiveMQQueue("ActiveMQ.DLQ"), ADMINS);
|
|
||||||
|
|
||||||
readAccess.put(new ActiveMQTopic("ActiveMQ.Advisory.>"), WILDCARD);
|
|
||||||
writeAccess.put(new ActiveMQTopic("ActiveMQ.Advisory.>"), WILDCARD);
|
|
||||||
|
|
||||||
DestinationMap adminAccess = new DefaultAuthorizationMap();
|
|
||||||
adminAccess.put(new ActiveMQQueue("TEST"), ADMINS);
|
|
||||||
adminAccess.put(new ActiveMQQueue("TEST"), USERS);
|
|
||||||
adminAccess.put(new ActiveMQQueue("ActiveMQ.DLQ"), ADMINS);
|
|
||||||
adminAccess.put(new ActiveMQTopic("ActiveMQ.Advisory.>"), WILDCARD);
|
|
||||||
|
|
||||||
return new SimpleAuthorizationMap(writeAccess, readAccess, adminAccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
AuthorizationPlugin authorizationPlugin = new AuthorizationPlugin(createAuthorizationMap());
|
|
||||||
|
|
||||||
broker.setPlugins(new BrokerPlugin[]{authorizationPlugin, new SimpleSecurityBrokerSystemTest.SimpleAuthenticationFactory()});
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
// lets disable the inapplicable tests
|
|
||||||
@Override
|
|
||||||
public void testTransientTopicMessage() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testDurableTopicMessage() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doTest() throws Exception {
|
|
||||||
timeToLive = 1000;
|
|
||||||
acknowledgeMode = Session.CLIENT_ACKNOWLEDGE;
|
|
||||||
makeConsumer();
|
|
||||||
sendMessages();
|
|
||||||
Thread.sleep(1000);
|
|
||||||
consumer.close();
|
|
||||||
|
|
||||||
Thread.sleep(1000);
|
|
||||||
// this should try to send expired messages to dlq
|
|
||||||
makeConsumer();
|
|
||||||
|
|
||||||
makeDlqConsumer();
|
|
||||||
for (int i = 0; i < messageCount; i++) {
|
|
||||||
Message msg = dlqConsumer.receive(1000);
|
|
||||||
assertMessage(msg, i);
|
|
||||||
assertNotNull("Should be a DLQ message for loop: " + i, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
if (dlqConnection != null) {
|
|
||||||
dlqConnection.close();
|
|
||||||
}
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Connection createConnection() throws Exception {
|
|
||||||
return getConnectionFactory().createConnection("user", "password");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void makeDlqConsumer() throws Exception {
|
|
||||||
dlqDestination = createDlqDestination();
|
|
||||||
dlqConnection = getConnectionFactory().createConnection("system", "manager");
|
|
||||||
dlqConnection.start();
|
|
||||||
dlqSession = dlqConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
|
|
||||||
dlqConsumer = dlqSession.createConsumer(dlqDestination);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Destination createDlqDestination() {
|
|
||||||
return new ActiveMQQueue("ActiveMQ.DLQ");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getDestinationString() {
|
|
||||||
return "TEST";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.QueueSubscriptionTest;
|
|
||||||
import org.apache.activemq.broker.region.policy.FixedCountSubscriptionRecoveryPolicy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.broker.region.policy.SimpleDispatchPolicy;
|
|
||||||
import org.apache.activemq.util.MessageIdList;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
@RunWith(BlockJUnit4ClassRunner.class)
|
|
||||||
public class SimpleDispatchPolicyTest extends QueueSubscriptionTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
policy.setDispatchPolicy(new SimpleDispatchPolicy());
|
|
||||||
policy.setSubscriptionRecoveryPolicy(new FixedCountSubscriptionRecoveryPolicy());
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
|
|
||||||
broker.setDestinationPolicy(pMap);
|
|
||||||
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersSmallMessagesLargePrefetch() throws Exception {
|
|
||||||
super.testOneProducerTwoConsumersSmallMessagesLargePrefetch();
|
|
||||||
|
|
||||||
// One consumer should have received all messages, and the rest none
|
|
||||||
// assertOneConsumerReceivedAllMessages(messageCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Test(timeout = 60 * 1000)
|
|
||||||
public void testOneProducerTwoConsumersLargeMessagesLargePrefetch() throws Exception {
|
|
||||||
super.testOneProducerTwoConsumersLargeMessagesLargePrefetch();
|
|
||||||
|
|
||||||
// One consumer should have received all messages, and the rest none
|
|
||||||
// assertOneConsumerReceivedAllMessages(messageCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void assertOneConsumerReceivedAllMessages(int messageCount) throws Exception {
|
|
||||||
boolean found = false;
|
|
||||||
for (Iterator<MessageConsumer> i = consumers.keySet().iterator(); i.hasNext(); ) {
|
|
||||||
MessageIdList messageIdList = consumers.get(i.next());
|
|
||||||
int count = messageIdList.getMessageCount();
|
|
||||||
if (count > 0) {
|
|
||||||
if (found) {
|
|
||||||
fail("No other consumers should have received any messages");
|
|
||||||
} else {
|
|
||||||
assertEquals("Consumer should have received all messages.", messageCount, count);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
fail("At least one consumer should have received all messages");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,131 +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.broker.policy;
|
|
||||||
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.TopicSubscriptionTest;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.broker.region.policy.StrictOrderDispatchPolicy;
|
|
||||||
import org.apache.activemq.util.MessageIdList;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
@RunWith(BlockJUnit4ClassRunner.class)
|
|
||||||
public class StrictOrderDispatchPolicyTest extends TopicSubscriptionTest {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
|
||||||
policy.setDispatchPolicy(new StrictOrderDispatchPolicy());
|
|
||||||
|
|
||||||
PolicyMap pMap = new PolicyMap();
|
|
||||||
pMap.setDefaultEntry(policy);
|
|
||||||
|
|
||||||
broker.setDestinationPolicy(pMap);
|
|
||||||
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Override
|
|
||||||
public void testOneProducerTwoConsumersLargeMessagesOnePrefetch() throws Exception {
|
|
||||||
super.testOneProducerTwoConsumersLargeMessagesOnePrefetch();
|
|
||||||
|
|
||||||
assertReceivedMessagesAreOrdered();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Override
|
|
||||||
public void testOneProducerTwoConsumersSmallMessagesOnePrefetch() throws Exception {
|
|
||||||
super.testOneProducerTwoConsumersSmallMessagesOnePrefetch();
|
|
||||||
|
|
||||||
assertReceivedMessagesAreOrdered();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Override
|
|
||||||
public void testOneProducerTwoConsumersSmallMessagesLargePrefetch() throws Exception {
|
|
||||||
super.testOneProducerTwoConsumersSmallMessagesLargePrefetch();
|
|
||||||
|
|
||||||
assertReceivedMessagesAreOrdered();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Override
|
|
||||||
public void testOneProducerTwoConsumersLargeMessagesLargePrefetch() throws Exception {
|
|
||||||
super.testOneProducerTwoConsumersLargeMessagesLargePrefetch();
|
|
||||||
|
|
||||||
assertReceivedMessagesAreOrdered();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Override
|
|
||||||
public void testOneProducerManyConsumersFewMessages() throws Exception {
|
|
||||||
super.testOneProducerManyConsumersFewMessages();
|
|
||||||
|
|
||||||
assertReceivedMessagesAreOrdered();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Override
|
|
||||||
public void testOneProducerManyConsumersManyMessages() throws Exception {
|
|
||||||
super.testOneProducerManyConsumersManyMessages();
|
|
||||||
|
|
||||||
assertReceivedMessagesAreOrdered();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Override
|
|
||||||
public void testManyProducersOneConsumer() throws Exception {
|
|
||||||
super.testManyProducersOneConsumer();
|
|
||||||
|
|
||||||
assertReceivedMessagesAreOrdered();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Override
|
|
||||||
public void testManyProducersManyConsumers() throws Exception {
|
|
||||||
super.testManyProducersManyConsumers();
|
|
||||||
|
|
||||||
assertReceivedMessagesAreOrdered();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void assertReceivedMessagesAreOrdered() throws Exception {
|
|
||||||
// If there is only one consumer, messages is definitely ordered
|
|
||||||
if (consumers.size() <= 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get basis of order
|
|
||||||
Iterator<MessageConsumer> i = consumers.keySet().iterator();
|
|
||||||
MessageIdList messageOrder = consumers.get(i.next());
|
|
||||||
|
|
||||||
for (; i.hasNext(); ) {
|
|
||||||
MessageIdList messageIdList = consumers.get(i.next());
|
|
||||||
assertTrue("Messages are not ordered.", messageOrder.equals(messageIdList));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright 2005-2006 The Apache Software Foundation
|
|
||||||
|
|
||||||
Licensed 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- this file can only be parsed using the xbean-spring library -->
|
|
||||||
<!-- START SNIPPET: xbean -->
|
|
||||||
<beans
|
|
||||||
xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
|
|
||||||
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
|
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
|
||||||
|
|
||||||
<broker persistent="false" xmlns="http://activemq.apache.org/schema/core">
|
|
||||||
|
|
||||||
<!-- lets define the dispatch policy -->
|
|
||||||
<destinationPolicy>
|
|
||||||
<policyMap>
|
|
||||||
<policyEntries>
|
|
||||||
<policyEntry topic="org.apache.>" producerFlowControl="false" memoryLimit="1mb">
|
|
||||||
|
|
||||||
<deadLetterStrategy>
|
|
||||||
<individualDeadLetterStrategy topicPrefix="Test.DLQ." />
|
|
||||||
</deadLetterStrategy>
|
|
||||||
<dispatchPolicy>
|
|
||||||
<strictOrderDispatchPolicy />
|
|
||||||
</dispatchPolicy>
|
|
||||||
<pendingSubscriberPolicy>
|
|
||||||
<vmCursor />
|
|
||||||
</pendingSubscriberPolicy>
|
|
||||||
</policyEntry>
|
|
||||||
|
|
||||||
<policyEntry queue="org.apache.>">
|
|
||||||
|
|
||||||
<deadLetterStrategy>
|
|
||||||
<individualDeadLetterStrategy queuePrefix="Test.DLQ."/>
|
|
||||||
</deadLetterStrategy>
|
|
||||||
<dispatchPolicy>
|
|
||||||
<strictOrderDispatchPolicy />
|
|
||||||
</dispatchPolicy>
|
|
||||||
<pendingQueuePolicy>
|
|
||||||
<vmQueueCursor />
|
|
||||||
</pendingQueuePolicy>
|
|
||||||
</policyEntry>
|
|
||||||
|
|
||||||
</policyEntries>
|
|
||||||
</policyMap>
|
|
||||||
</destinationPolicy>
|
|
||||||
</broker>
|
|
||||||
|
|
||||||
</beans>
|
|
||||||
<!-- END SNIPPET: xbean -->
|
|
|
@ -1,60 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!--
|
|
||||||
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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- this file can only be parsed using the xbean-spring library -->
|
|
||||||
<!-- START SNIPPET: xbean -->
|
|
||||||
<beans
|
|
||||||
xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
|
||||||
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd
|
|
||||||
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
|
|
||||||
|
|
||||||
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
|
|
||||||
|
|
||||||
<broker persistent="false" xmlns="http://activemq.apache.org/schema/core">
|
|
||||||
|
|
||||||
<!-- lets define the dispatch policy -->
|
|
||||||
<destinationPolicy>
|
|
||||||
<policyMap>
|
|
||||||
<policyEntries>
|
|
||||||
<policyEntry topic="org.apache.>">
|
|
||||||
<deadLetterStrategy>
|
|
||||||
<individualDeadLetterStrategy topicPrefix="Test.DLQ." processNonPersistent="true" />
|
|
||||||
</deadLetterStrategy>
|
|
||||||
<dispatchPolicy>
|
|
||||||
<strictOrderDispatchPolicy />
|
|
||||||
</dispatchPolicy>
|
|
||||||
</policyEntry>
|
|
||||||
|
|
||||||
<policyEntry queue="org.apache.>">
|
|
||||||
<deadLetterStrategy>
|
|
||||||
<individualDeadLetterStrategy queuePrefix="Test.DLQ." processNonPersistent="true"/>
|
|
||||||
</deadLetterStrategy>
|
|
||||||
<dispatchPolicy>
|
|
||||||
<strictOrderDispatchPolicy />
|
|
||||||
</dispatchPolicy>
|
|
||||||
</policyEntry>
|
|
||||||
|
|
||||||
</policyEntries>
|
|
||||||
</policyMap>
|
|
||||||
</destinationPolicy>
|
|
||||||
</broker>
|
|
||||||
|
|
||||||
</beans>
|
|
||||||
<!-- END SNIPPET: xbean -->
|
|
|
@ -1,112 +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.broker.region;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageListener;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.util.Wait;
|
|
||||||
import org.apache.activemq.util.Wait.Condition;
|
|
||||||
|
|
||||||
public class DestinationGCTest extends EmbeddedBrokerTestSupport {
|
|
||||||
|
|
||||||
ActiveMQQueue queue = new ActiveMQQueue("TEST");
|
|
||||||
ActiveMQQueue otherQueue = new ActiveMQQueue("TEST-OTHER");
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = super.createBroker();
|
|
||||||
broker.setDestinations(new ActiveMQDestination[]{queue});
|
|
||||||
broker.setSchedulePeriodForDestinationPurge(1000);
|
|
||||||
broker.setMaxPurgedDestinationsPerSweep(1);
|
|
||||||
PolicyEntry entry = new PolicyEntry();
|
|
||||||
entry.setGcInactiveDestinations(true);
|
|
||||||
entry.setInactiveTimeoutBeforeGC(3000);
|
|
||||||
PolicyMap map = new PolicyMap();
|
|
||||||
map.setDefaultEntry(entry);
|
|
||||||
broker.setDestinationPolicy(map);
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDestinationGCWithActiveConsumers() throws Exception {
|
|
||||||
assertEquals(1, broker.getAdminView().getQueues().length);
|
|
||||||
|
|
||||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost?create=false");
|
|
||||||
Connection connection = factory.createConnection();
|
|
||||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
session.createProducer(otherQueue).close();
|
|
||||||
MessageConsumer consumer = session.createConsumer(queue);
|
|
||||||
consumer.setMessageListener(new MessageListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessage(Message message) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connection.start();
|
|
||||||
|
|
||||||
TimeUnit.SECONDS.sleep(5);
|
|
||||||
|
|
||||||
assertTrue("After GC runs there should be one Queue.", Wait.waitFor(new Condition() {
|
|
||||||
@Override
|
|
||||||
public boolean isSatisified() throws Exception {
|
|
||||||
return broker.getAdminView().getQueues().length == 1;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDestinationGc() throws Exception {
|
|
||||||
assertEquals(1, broker.getAdminView().getQueues().length);
|
|
||||||
assertTrue("After GC runs the Queue should be empty.", Wait.waitFor(new Condition() {
|
|
||||||
@Override
|
|
||||||
public boolean isSatisified() throws Exception {
|
|
||||||
return broker.getAdminView().getQueues().length == 0;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDestinationGcLimit() throws Exception {
|
|
||||||
|
|
||||||
broker.getAdminView().addQueue("TEST1");
|
|
||||||
broker.getAdminView().addQueue("TEST2");
|
|
||||||
broker.getAdminView().addQueue("TEST3");
|
|
||||||
broker.getAdminView().addQueue("TEST4");
|
|
||||||
|
|
||||||
assertEquals(5, broker.getAdminView().getQueues().length);
|
|
||||||
Thread.sleep(7000);
|
|
||||||
int queues = broker.getAdminView().getQueues().length;
|
|
||||||
assertTrue(queues > 0 && queues < 5);
|
|
||||||
assertTrue("After GC runs the Queue should be empty.", Wait.waitFor(new Condition() {
|
|
||||||
@Override
|
|
||||||
public boolean isSatisified() throws Exception {
|
|
||||||
return broker.getAdminView().getQueues().length == 0;
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,116 +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.broker.region;
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
|
|
||||||
import org.apache.activemq.CombinationTestSupport;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
|
|
||||||
// from https://issues.apache.org/activemq/browse/AMQ-2216
|
|
||||||
public class DestinationRemoveRestartTest extends CombinationTestSupport {
|
|
||||||
|
|
||||||
private final static String destinationName = "TEST";
|
|
||||||
public byte destinationType = ActiveMQDestination.QUEUE_TYPE;
|
|
||||||
BrokerService broker;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
broker = createBroker();
|
|
||||||
}
|
|
||||||
|
|
||||||
private BrokerService createBroker() throws Exception {
|
|
||||||
BrokerService broker = new BrokerService();
|
|
||||||
broker.setUseJmx(false);
|
|
||||||
broker.setPersistent(true);
|
|
||||||
broker.setDeleteAllMessagesOnStartup(true);
|
|
||||||
broker.start();
|
|
||||||
return broker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
broker.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initCombosForTestCheckDestinationRemoveActionAfterRestart() {
|
|
||||||
addCombinationValues("destinationType", new Object[]{Byte.valueOf(ActiveMQDestination.QUEUE_TYPE), Byte.valueOf(ActiveMQDestination.TOPIC_TYPE)});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCheckDestinationRemoveActionAfterRestart() throws Exception {
|
|
||||||
doAddDestination();
|
|
||||||
doRemoveDestination();
|
|
||||||
broker.stop();
|
|
||||||
broker.waitUntilStopped();
|
|
||||||
broker = createBroker();
|
|
||||||
doCheckRemoveActionAfterRestart();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doAddDestination() throws Exception {
|
|
||||||
boolean res = false;
|
|
||||||
|
|
||||||
ActiveMQDestination amqDestination = ActiveMQDestination.createDestination(destinationName, destinationType);
|
|
||||||
broker.getRegionBroker().addDestination(broker.getAdminConnectionContext(), amqDestination, true);
|
|
||||||
|
|
||||||
final ActiveMQDestination[] list = broker.getRegionBroker().getDestinations();
|
|
||||||
for (final ActiveMQDestination element : list) {
|
|
||||||
final Destination destination = broker.getDestination(element);
|
|
||||||
if (destination.getActiveMQDestination().getPhysicalName().equals(destinationName)) {
|
|
||||||
res = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue("Adding destination Failed", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doRemoveDestination() throws Exception {
|
|
||||||
boolean res = true;
|
|
||||||
|
|
||||||
broker.removeDestination(ActiveMQDestination.createDestination(destinationName, destinationType));
|
|
||||||
final ActiveMQDestination[] list = broker.getRegionBroker().getDestinations();
|
|
||||||
for (final ActiveMQDestination element : list) {
|
|
||||||
final Destination destination = broker.getDestination(element);
|
|
||||||
if (destination.getActiveMQDestination().getPhysicalName().equals(destinationName)) {
|
|
||||||
res = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue("Removing destination Failed", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doCheckRemoveActionAfterRestart() throws Exception {
|
|
||||||
boolean res = true;
|
|
||||||
|
|
||||||
final ActiveMQDestination[] list = broker.getRegionBroker().getDestinations();
|
|
||||||
for (final ActiveMQDestination element : list) {
|
|
||||||
final Destination destination = broker.getDestination(element);
|
|
||||||
if (destination.getActiveMQDestination().getPhysicalName().equals(destinationName)) {
|
|
||||||
res = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue("The removed destination is reloaded after restart !", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return suite(DestinationRemoveRestartTest.class);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,404 +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.broker.region;
|
|
||||||
|
|
||||||
import javax.jms.InvalidSelectorException;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Vector;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
|
||||||
import org.apache.activemq.broker.ProducerBrokerExchange;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ActiveMQTextMessage;
|
|
||||||
import org.apache.activemq.command.ConsumerInfo;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.command.MessageAck;
|
|
||||||
import org.apache.activemq.command.MessageDispatchNotification;
|
|
||||||
import org.apache.activemq.command.MessageId;
|
|
||||||
import org.apache.activemq.command.MessagePull;
|
|
||||||
import org.apache.activemq.command.ProducerInfo;
|
|
||||||
import org.apache.activemq.command.Response;
|
|
||||||
import org.apache.activemq.filter.MessageEvaluationContext;
|
|
||||||
import org.apache.activemq.state.ProducerState;
|
|
||||||
import org.apache.activemq.store.MessageStore;
|
|
||||||
import org.apache.activemq.store.PersistenceAdapter;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author gtully
|
|
||||||
* @see https://issues.apache.org/activemq/browse/AMQ-2020
|
|
||||||
**/
|
|
||||||
public class QueueDuplicatesFromStoreTest extends TestCase {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(QueueDuplicatesFromStoreTest.class);
|
|
||||||
|
|
||||||
ActiveMQQueue destination = new ActiveMQQueue("queue-" + QueueDuplicatesFromStoreTest.class.getSimpleName());
|
|
||||||
BrokerService brokerService;
|
|
||||||
|
|
||||||
final static String mesageIdRoot = "11111:22222:";
|
|
||||||
final int messageBytesSize = 256;
|
|
||||||
final String text = new String(new byte[messageBytesSize]);
|
|
||||||
|
|
||||||
final int ackStartIndex = 100;
|
|
||||||
final int ackWindow = 50;
|
|
||||||
final int ackBatchSize = 50;
|
|
||||||
final int fullWindow = 200;
|
|
||||||
protected int count = 5000;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
brokerService = createBroker();
|
|
||||||
brokerService.setUseJmx(false);
|
|
||||||
brokerService.deleteAllMessages();
|
|
||||||
brokerService.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BrokerService createBroker() throws Exception {
|
|
||||||
return new BrokerService();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
brokerService.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testNoDuplicateAfterCacheFullAndAckedWithLargeAuditDepth() throws Exception {
|
|
||||||
doTestNoDuplicateAfterCacheFullAndAcked(1024 * 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testNoDuplicateAfterCacheFullAndAckedWithSmallAuditDepth() throws Exception {
|
|
||||||
doTestNoDuplicateAfterCacheFullAndAcked(512);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doTestNoDuplicateAfterCacheFullAndAcked(final int auditDepth) throws Exception {
|
|
||||||
final PersistenceAdapter persistenceAdapter = brokerService.getPersistenceAdapter();
|
|
||||||
final MessageStore queueMessageStore = persistenceAdapter.createQueueMessageStore(destination);
|
|
||||||
final ConnectionContext contextNotInTx = new ConnectionContext();
|
|
||||||
final ConsumerInfo consumerInfo = new ConsumerInfo();
|
|
||||||
final DestinationStatistics destinationStatistics = new DestinationStatistics();
|
|
||||||
consumerInfo.setExclusive(true);
|
|
||||||
final Queue queue = new Queue(brokerService, destination, queueMessageStore, destinationStatistics, brokerService.getTaskRunnerFactory());
|
|
||||||
|
|
||||||
// a workaround for this issue
|
|
||||||
// queue.setUseCache(false);
|
|
||||||
queue.systemUsage.getMemoryUsage().setLimit(1024 * 1024 * 10);
|
|
||||||
queue.setMaxAuditDepth(auditDepth);
|
|
||||||
queue.initialize();
|
|
||||||
queue.start();
|
|
||||||
|
|
||||||
ProducerBrokerExchange producerExchange = new ProducerBrokerExchange();
|
|
||||||
ProducerInfo producerInfo = new ProducerInfo();
|
|
||||||
ProducerState producerState = new ProducerState(producerInfo);
|
|
||||||
producerExchange.setProducerState(producerState);
|
|
||||||
producerExchange.setConnectionContext(contextNotInTx);
|
|
||||||
|
|
||||||
final CountDownLatch receivedLatch = new CountDownLatch(count);
|
|
||||||
final AtomicLong ackedCount = new AtomicLong(0);
|
|
||||||
final AtomicLong enqueueCounter = new AtomicLong(0);
|
|
||||||
final Vector<String> errors = new Vector<>();
|
|
||||||
|
|
||||||
// populate the queue store, exceed memory limit so that cache is disabled
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
Message message = getMessage(i);
|
|
||||||
queue.send(producerExchange, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals("store count is correct", count, queueMessageStore.getMessageCount());
|
|
||||||
|
|
||||||
// pull from store in small windows
|
|
||||||
Subscription subscription = new Subscription() {
|
|
||||||
|
|
||||||
private SubscriptionStatistics subscriptionStatistics = new SubscriptionStatistics();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getPendingMessageSize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void add(MessageReference node) throws Exception {
|
|
||||||
if (enqueueCounter.get() != node.getMessageId().getProducerSequenceId()) {
|
|
||||||
errors.add("Not in sequence at: " + enqueueCounter.get() + ", received: " + node.getMessageId().getProducerSequenceId());
|
|
||||||
}
|
|
||||||
assertEquals("is in order", enqueueCounter.get(), node.getMessageId().getProducerSequenceId());
|
|
||||||
receivedLatch.countDown();
|
|
||||||
enqueueCounter.incrementAndGet();
|
|
||||||
node.decrementReferenceCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void add(ConnectionContext context, Destination destination) throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int countBeforeFull() {
|
|
||||||
if (isFull()) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return fullWindow - (int) (enqueueCounter.get() - ackedCount.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void gc() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConsumerInfo getConsumerInfo() {
|
|
||||||
return consumerInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConnectionContext getContext() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getDequeueCounter() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getDispatchedCounter() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getDispatchedQueueSize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getEnqueueCounter() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getInFlightSize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getInFlightUsage() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ObjectName getObjectName() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPendingQueueSize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPrefetchSize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSelector() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBrowser() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFull() {
|
|
||||||
return (enqueueCounter.get() - ackedCount.get()) >= fullWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isHighWaterMark() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLowWaterMark() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRecoveryRequired() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(MessageReference node, MessageEvaluationContext context) throws IOException {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(ActiveMQDestination destination) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void processMessageDispatchNotification(MessageDispatchNotification mdn) throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Response pullMessage(ConnectionContext context, MessagePull pull) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isWildcard() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<MessageReference> remove(ConnectionContext context, Destination destination) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setObjectName(ObjectName objectName) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSelector(String selector) throws InvalidSelectorException, UnsupportedOperationException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateConsumerPrefetch(int newPrefetch) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addRecoveredMessage(ConnectionContext context, MessageReference message) throws Exception {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActiveMQDestination getActiveMQDestination() {
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void acknowledge(ConnectionContext context, MessageAck ack) throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCursorMemoryHighWaterMark() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCursorMemoryHighWaterMark(int cursorMemoryHighWaterMark) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSlowConsumer() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unmatched(MessageReference node) throws IOException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getTimeOfLastMessageAck() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getConsumedCount() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void incrementConsumedCount() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resetConsumedCount() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SubscriptionStatistics getSubscriptionStatistics() {
|
|
||||||
return subscriptionStatistics;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getInFlightMessageSize() {
|
|
||||||
return subscriptionStatistics.getInflightMessageSize().getTotalSize();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
queue.addSubscription(contextNotInTx, subscription);
|
|
||||||
int removeIndex = 0;
|
|
||||||
do {
|
|
||||||
// Simulate periodic acks in small but recent windows
|
|
||||||
long receivedCount = enqueueCounter.get();
|
|
||||||
if (receivedCount > ackStartIndex) {
|
|
||||||
if (receivedCount >= removeIndex + ackWindow) {
|
|
||||||
for (int j = 0; j < ackBatchSize; j++, removeIndex++) {
|
|
||||||
ackedCount.incrementAndGet();
|
|
||||||
MessageAck ack = new MessageAck();
|
|
||||||
ack.setLastMessageId(new MessageId(mesageIdRoot + removeIndex));
|
|
||||||
ack.setMessageCount(1);
|
|
||||||
queue.removeMessage(contextNotInTx, subscription, new IndirectMessageReference(getMessage(removeIndex)), ack);
|
|
||||||
queue.wakeup();
|
|
||||||
|
|
||||||
}
|
|
||||||
if (removeIndex % 1000 == 0) {
|
|
||||||
LOG.info("acked: " + removeIndex);
|
|
||||||
persistenceAdapter.checkpoint(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (!receivedLatch.await(0, TimeUnit.MILLISECONDS) && errors.isEmpty());
|
|
||||||
|
|
||||||
assertTrue("There are no errors: " + errors, errors.isEmpty());
|
|
||||||
assertEquals(count, enqueueCounter.get());
|
|
||||||
assertEquals("store count is correct", count - removeIndex, queueMessageStore.getMessageCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Message getMessage(int i) throws Exception {
|
|
||||||
ActiveMQTextMessage message = new ActiveMQTextMessage();
|
|
||||||
message.setMessageId(new MessageId(mesageIdRoot + i));
|
|
||||||
message.setDestination(destination);
|
|
||||||
message.setPersistent(true);
|
|
||||||
message.setResponseRequired(true);
|
|
||||||
message.setText("Msg:" + i + " " + text);
|
|
||||||
assertEquals(message.getMessageId().getProducerSequenceId(), i);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,253 +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.broker.region;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.Connection;
|
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
|
||||||
import org.apache.activemq.broker.Connector;
|
|
||||||
import org.apache.activemq.broker.ProducerBrokerExchange;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ActiveMQTextMessage;
|
|
||||||
import org.apache.activemq.command.Command;
|
|
||||||
import org.apache.activemq.command.ConnectionControl;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.command.MessageId;
|
|
||||||
import org.apache.activemq.command.ProducerInfo;
|
|
||||||
import org.apache.activemq.command.Response;
|
|
||||||
import org.apache.activemq.state.ProducerState;
|
|
||||||
import org.apache.activemq.store.MessageStore;
|
|
||||||
import org.apache.activemq.store.PersistenceAdapter;
|
|
||||||
import org.apache.activemq.usage.MemoryUsage;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
public class QueueOptimizedDispatchExceptionTest {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(QueueOptimizedDispatchExceptionTest.class);
|
|
||||||
|
|
||||||
private static final String brokerName = "testBroker";
|
|
||||||
private static final String brokerUrl = "vm://" + brokerName;
|
|
||||||
private static final int count = 50;
|
|
||||||
|
|
||||||
private final static String mesageIdRoot = "11111:22222:";
|
|
||||||
private final ActiveMQQueue destination = new ActiveMQQueue("queue-" + QueueOptimizedDispatchExceptionTest.class.getSimpleName());
|
|
||||||
private final int messageBytesSize = 256;
|
|
||||||
private final String text = new String(new byte[messageBytesSize]);
|
|
||||||
|
|
||||||
private BrokerService broker;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
|
|
||||||
// Setup and start the broker
|
|
||||||
broker = new BrokerService();
|
|
||||||
broker.setBrokerName(brokerName);
|
|
||||||
broker.setPersistent(false);
|
|
||||||
broker.setSchedulerSupport(false);
|
|
||||||
broker.setUseJmx(false);
|
|
||||||
broker.setUseShutdownHook(false);
|
|
||||||
broker.addConnector(brokerUrl);
|
|
||||||
|
|
||||||
// Start the broker
|
|
||||||
broker.start();
|
|
||||||
broker.waitUntilStarted();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
broker.stop();
|
|
||||||
broker.waitUntilStopped();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class MockMemoryUsage extends MemoryUsage {
|
|
||||||
|
|
||||||
private boolean full = true;
|
|
||||||
|
|
||||||
public void setFull(boolean full) {
|
|
||||||
this.full = full;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFull() {
|
|
||||||
return full;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void TestOptimizedDispatchCME() throws Exception {
|
|
||||||
final PersistenceAdapter persistenceAdapter = broker.getPersistenceAdapter();
|
|
||||||
final MessageStore queueMessageStore = persistenceAdapter.createQueueMessageStore(destination);
|
|
||||||
final ConnectionContext contextNotInTx = new ConnectionContext();
|
|
||||||
contextNotInTx.setConnection(new Connection() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stop() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start() throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateClient(ConnectionControl control) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void serviceExceptionAsync(IOException e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void serviceException(Throwable error) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Response service(Command command) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSlow() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isNetworkConnection() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isManageable() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFaultTolerantConnection() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConnected() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBlocked() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isActive() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConnectionStatistics getStatistics() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRemoteAddress() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getDispatchQueueSize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Connector getConnector() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getConnectionId() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dispatchSync(Command message) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dispatchAsync(Command command) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getActiveTransactionCount() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long getOldestActiveTransactionDuration() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
final DestinationStatistics destinationStatistics = new DestinationStatistics();
|
|
||||||
final Queue queue = new Queue(broker, destination, queueMessageStore, destinationStatistics, broker.getTaskRunnerFactory());
|
|
||||||
|
|
||||||
final MockMemoryUsage usage = new MockMemoryUsage();
|
|
||||||
|
|
||||||
queue.setOptimizedDispatch(true);
|
|
||||||
queue.initialize();
|
|
||||||
queue.start();
|
|
||||||
queue.memoryUsage = usage;
|
|
||||||
|
|
||||||
ProducerBrokerExchange producerExchange = new ProducerBrokerExchange();
|
|
||||||
ProducerInfo producerInfo = new ProducerInfo();
|
|
||||||
ProducerState producerState = new ProducerState(producerInfo);
|
|
||||||
producerExchange.setProducerState(producerState);
|
|
||||||
producerExchange.setConnectionContext(contextNotInTx);
|
|
||||||
|
|
||||||
// populate the queue store, exceed memory limit so that cache is disabled
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
Message message = getMessage(i);
|
|
||||||
queue.send(producerExchange, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
usage.setFull(false);
|
|
||||||
|
|
||||||
try {
|
|
||||||
queue.wakeup();
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error("Queue threw an unexpected exception: " + e.toString());
|
|
||||||
fail("Should not throw an exception.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Message getMessage(int i) throws Exception {
|
|
||||||
ActiveMQTextMessage message = new ActiveMQTextMessage();
|
|
||||||
message.setMessageId(new MessageId(mesageIdRoot + i));
|
|
||||||
message.setDestination(destination);
|
|
||||||
message.setPersistent(false);
|
|
||||||
message.setResponseRequired(true);
|
|
||||||
message.setText("Msg:" + i + " " + text);
|
|
||||||
assertEquals(message.getMessageId().getProducerSequenceId(), i);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,209 +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.broker.region;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.ConnectionFactory;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Queue;
|
|
||||||
import javax.jms.Session;
|
|
||||||
import javax.jms.TextMessage;
|
|
||||||
import javax.management.MalformedObjectNameException;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.CombinationTestSupport;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.jmx.QueueViewMBean;
|
|
||||||
import org.apache.activemq.broker.region.policy.FilePendingQueueMessageStoragePolicy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PendingQueueMessageStoragePolicy;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
|
||||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
|
||||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
|
||||||
import org.apache.activemq.util.DefaultTestAppender;
|
|
||||||
import org.apache.log4j.Appender;
|
|
||||||
import org.apache.log4j.Level;
|
|
||||||
import org.apache.log4j.spi.LoggingEvent;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class QueuePurgeTest extends CombinationTestSupport {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(QueuePurgeTest.class);
|
|
||||||
private static final int NUM_TO_SEND = 20000;
|
|
||||||
private final String MESSAGE_TEXT = new String(new byte[1024]);
|
|
||||||
BrokerService broker;
|
|
||||||
ConnectionFactory factory;
|
|
||||||
Connection connection;
|
|
||||||
Session session;
|
|
||||||
Queue queue;
|
|
||||||
MessageConsumer consumer;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
setMaxTestTime(10 * 60 * 1000); // 10 mins
|
|
||||||
setAutoFail(true);
|
|
||||||
super.setUp();
|
|
||||||
broker = new BrokerService();
|
|
||||||
|
|
||||||
File testDataDir = new File("target/activemq-data/QueuePurgeTest");
|
|
||||||
broker.setDataDirectoryFile(testDataDir);
|
|
||||||
broker.setUseJmx(true);
|
|
||||||
broker.setDeleteAllMessagesOnStartup(true);
|
|
||||||
broker.getSystemUsage().getMemoryUsage().setLimit(1024L * 1024 * 64);
|
|
||||||
KahaDBPersistenceAdapter persistenceAdapter = new KahaDBPersistenceAdapter();
|
|
||||||
persistenceAdapter.setDirectory(new File(testDataDir, "kahadb"));
|
|
||||||
broker.setPersistenceAdapter(persistenceAdapter);
|
|
||||||
broker.addConnector("tcp://localhost:0");
|
|
||||||
broker.start();
|
|
||||||
factory = new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getConnectUri().toString());
|
|
||||||
connection = factory.createConnection();
|
|
||||||
connection.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
if (consumer != null) {
|
|
||||||
consumer.close();
|
|
||||||
}
|
|
||||||
session.close();
|
|
||||||
connection.stop();
|
|
||||||
connection.close();
|
|
||||||
broker.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testPurgeLargeQueue() throws Exception {
|
|
||||||
applyBrokerSpoolingPolicy();
|
|
||||||
createProducerAndSendMessages(NUM_TO_SEND);
|
|
||||||
QueueViewMBean proxy = getProxyToQueueViewMBean();
|
|
||||||
LOG.info("purging..");
|
|
||||||
|
|
||||||
org.apache.log4j.Logger log4jLogger = org.apache.log4j.Logger.getLogger(org.apache.activemq.broker.region.Queue.class);
|
|
||||||
final AtomicBoolean gotPurgeLogMessage = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
Appender appender = new DefaultTestAppender() {
|
|
||||||
@Override
|
|
||||||
public void doAppend(LoggingEvent event) {
|
|
||||||
if (event.getMessage() instanceof String) {
|
|
||||||
String message = (String) event.getMessage();
|
|
||||||
if (message.contains("purged of " + NUM_TO_SEND + " messages")) {
|
|
||||||
LOG.info("Received a log message: {} ", event.getMessage());
|
|
||||||
gotPurgeLogMessage.set(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Level level = log4jLogger.getLevel();
|
|
||||||
log4jLogger.setLevel(Level.INFO);
|
|
||||||
log4jLogger.addAppender(appender);
|
|
||||||
try {
|
|
||||||
|
|
||||||
proxy.purge();
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
log4jLogger.setLevel(level);
|
|
||||||
log4jLogger.removeAppender(appender);
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals("Queue size is not zero, it's " + proxy.getQueueSize(), 0, proxy.getQueueSize());
|
|
||||||
assertTrue("cache is disabled, temp store being used", !proxy.isCacheEnabled());
|
|
||||||
assertTrue("got expected info purge log message", gotPurgeLogMessage.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testRepeatedExpiryProcessingOfLargeQueue() throws Exception {
|
|
||||||
applyBrokerSpoolingPolicy();
|
|
||||||
final int expiryPeriod = 500;
|
|
||||||
applyExpiryDuration(expiryPeriod);
|
|
||||||
createProducerAndSendMessages(NUM_TO_SEND);
|
|
||||||
QueueViewMBean proxy = getProxyToQueueViewMBean();
|
|
||||||
LOG.info("waiting for expiry to kick in a bunch of times to verify it does not blow mem");
|
|
||||||
Thread.sleep(5000);
|
|
||||||
assertEquals("Queue size is has not changed " + proxy.getQueueSize(), NUM_TO_SEND, proxy.getQueueSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyExpiryDuration(int i) {
|
|
||||||
broker.getDestinationPolicy().getDefaultEntry().setExpireMessagesPeriod(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyBrokerSpoolingPolicy() {
|
|
||||||
PolicyMap policyMap = new PolicyMap();
|
|
||||||
PolicyEntry defaultEntry = new PolicyEntry();
|
|
||||||
defaultEntry.setProducerFlowControl(false);
|
|
||||||
PendingQueueMessageStoragePolicy pendingQueuePolicy = new FilePendingQueueMessageStoragePolicy();
|
|
||||||
defaultEntry.setPendingQueuePolicy(pendingQueuePolicy);
|
|
||||||
policyMap.setDefaultEntry(defaultEntry);
|
|
||||||
broker.setDestinationPolicy(policyMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testPurgeLargeQueueWithConsumer() throws Exception {
|
|
||||||
applyBrokerSpoolingPolicy();
|
|
||||||
createProducerAndSendMessages(NUM_TO_SEND);
|
|
||||||
QueueViewMBean proxy = getProxyToQueueViewMBean();
|
|
||||||
createConsumer();
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
LOG.info("purging..");
|
|
||||||
proxy.purge();
|
|
||||||
LOG.info("purge done: " + (System.currentTimeMillis() - start) + "ms");
|
|
||||||
assertEquals("Queue size is not zero, it's " + proxy.getQueueSize(), 0, proxy.getQueueSize());
|
|
||||||
assertEquals("usage goes to duck", 0, proxy.getMemoryPercentUsage());
|
|
||||||
Message msg;
|
|
||||||
do {
|
|
||||||
msg = consumer.receive(1000);
|
|
||||||
if (msg != null) {
|
|
||||||
msg.acknowledge();
|
|
||||||
}
|
|
||||||
} while (msg != null);
|
|
||||||
assertEquals("Queue size not valid", 0, proxy.getQueueSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
private QueueViewMBean getProxyToQueueViewMBean() throws MalformedObjectNameException, JMSException {
|
|
||||||
ObjectName queueViewMBeanName = new ObjectName("org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=" + queue.getQueueName());
|
|
||||||
QueueViewMBean proxy = (QueueViewMBean) broker.getManagementContext().newProxyInstance(queueViewMBeanName, QueueViewMBean.class, true);
|
|
||||||
return proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createProducerAndSendMessages(int numToSend) throws Exception {
|
|
||||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
|
||||||
queue = session.createQueue("test1");
|
|
||||||
MessageProducer producer = session.createProducer(queue);
|
|
||||||
for (int i = 0; i < numToSend; i++) {
|
|
||||||
TextMessage message = session.createTextMessage(MESSAGE_TEXT + i);
|
|
||||||
if (i != 0 && i % 10000 == 0) {
|
|
||||||
LOG.info("sent: " + i);
|
|
||||||
}
|
|
||||||
producer.send(message);
|
|
||||||
}
|
|
||||||
producer.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createConsumer() throws Exception {
|
|
||||||
consumer = session.createConsumer(queue);
|
|
||||||
// wait for buffer fill out
|
|
||||||
Thread.sleep(5 * 1000);
|
|
||||||
for (int i = 0; i < 500; ++i) {
|
|
||||||
Message message = consumer.receive();
|
|
||||||
message.acknowledge();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,249 +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.broker.region;
|
|
||||||
|
|
||||||
import javax.jms.Connection;
|
|
||||||
import javax.jms.JMSException;
|
|
||||||
import javax.jms.Message;
|
|
||||||
import javax.jms.MessageConsumer;
|
|
||||||
import javax.jms.MessageListener;
|
|
||||||
import javax.jms.MessageProducer;
|
|
||||||
import javax.jms.Queue;
|
|
||||||
import javax.jms.Session;
|
|
||||||
|
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Confirm that the broker does not resend unacknowledged messages during a broker shutdown.
|
|
||||||
*/
|
|
||||||
public class QueueResendDuringShutdownTest {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(QueueResendDuringShutdownTest.class);
|
|
||||||
public static final int NUM_CONNECTION_TO_TEST = 8;
|
|
||||||
|
|
||||||
private static boolean iterationFoundFailure = false;
|
|
||||||
|
|
||||||
private BrokerService broker;
|
|
||||||
private ActiveMQConnectionFactory factory;
|
|
||||||
private Connection[] connections;
|
|
||||||
private Connection producerConnection;
|
|
||||||
private Queue queue;
|
|
||||||
|
|
||||||
private final Object messageReceiveSync = new Object();
|
|
||||||
private int receiveCount;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
this.receiveCount = 0;
|
|
||||||
|
|
||||||
this.broker = new BrokerService();
|
|
||||||
this.broker.setPersistent(false);
|
|
||||||
this.broker.start();
|
|
||||||
this.broker.waitUntilStarted();
|
|
||||||
|
|
||||||
this.factory = new ActiveMQConnectionFactory(broker.getVmConnectorURI());
|
|
||||||
this.queue = new ActiveMQQueue("TESTQUEUE");
|
|
||||||
|
|
||||||
connections = new Connection[NUM_CONNECTION_TO_TEST];
|
|
||||||
int iter = 0;
|
|
||||||
while (iter < NUM_CONNECTION_TO_TEST) {
|
|
||||||
this.connections[iter] = factory.createConnection();
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.producerConnection = factory.createConnection();
|
|
||||||
this.producerConnection.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void cleanup() throws Exception {
|
|
||||||
for (Connection oneConnection : connections) {
|
|
||||||
if (oneConnection != null) {
|
|
||||||
closeConnection(oneConnection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
connections = null;
|
|
||||||
|
|
||||||
if (this.producerConnection != null) {
|
|
||||||
closeConnection(this.producerConnection);
|
|
||||||
this.producerConnection = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.broker.stop();
|
|
||||||
this.broker.waitUntilStopped();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 3000)
|
|
||||||
public void testRedeliverAtBrokerShutdownAutoAckMsgListenerIter1() throws Throwable {
|
|
||||||
runTestIteration();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 3000)
|
|
||||||
public void testRedeliverAtBrokerShutdownAutoAckMsgListenerIter2() throws Throwable {
|
|
||||||
runTestIteration();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 3000)
|
|
||||||
public void testRedeliverAtBrokerShutdownAutoAckMsgListenerIter3() throws Throwable {
|
|
||||||
runTestIteration();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run one iteration of the test, skipping it if a failure was found on a prior iteration since a single failure is
|
|
||||||
* enough. Also keep track of the state of failure for the iteration.
|
|
||||||
*/
|
|
||||||
protected void runTestIteration() throws Throwable {
|
|
||||||
if (iterationFoundFailure) {
|
|
||||||
LOG.info("skipping test iteration; failure previously detected");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
testRedeliverAtBrokerShutdownAutoAckMsgListener();
|
|
||||||
} catch (Throwable thrown) {
|
|
||||||
iterationFoundFailure = true;
|
|
||||||
throw thrown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void testRedeliverAtBrokerShutdownAutoAckMsgListener() throws Exception {
|
|
||||||
// Start consumers on all of the connections
|
|
||||||
for (Connection oneConnection : connections) {
|
|
||||||
MessageConsumer consumer = startupConsumer(oneConnection, false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
configureMessageListener(consumer);
|
|
||||||
oneConnection.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send one message to the Queue and wait a short time for the dispatch to occur.
|
|
||||||
this.sendMessage();
|
|
||||||
waitForMessage(1000);
|
|
||||||
|
|
||||||
// Verify one consumer received it
|
|
||||||
assertEquals(1, this.receiveCount);
|
|
||||||
|
|
||||||
// Shutdown the broker
|
|
||||||
this.broker.stop();
|
|
||||||
this.broker.waitUntilStopped();
|
|
||||||
delay(100, "give queue time flush");
|
|
||||||
|
|
||||||
// Verify still only one consumer received it
|
|
||||||
assertEquals(1, this.receiveCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a consumer on the given connection using the session transaction and acknowledge settings given.
|
|
||||||
*/
|
|
||||||
protected MessageConsumer startupConsumer(Connection conn, boolean transInd, int ackMode) throws JMSException {
|
|
||||||
Session sess;
|
|
||||||
MessageConsumer consumer;
|
|
||||||
|
|
||||||
sess = conn.createSession(transInd, ackMode);
|
|
||||||
consumer = sess.createConsumer(queue);
|
|
||||||
|
|
||||||
return consumer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark the receipt of a message from one of the consumers.
|
|
||||||
*/
|
|
||||||
protected void messageReceived() {
|
|
||||||
synchronized (this) {
|
|
||||||
this.receiveCount++;
|
|
||||||
synchronized (this.messageReceiveSync) {
|
|
||||||
this.messageReceiveSync.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup the MessageListener for the given consumer. The listener uses a long delay on receiving the message to
|
|
||||||
* simulate the reported case of problems at shutdown caused by a message listener's connection closing while it is
|
|
||||||
* still processing.
|
|
||||||
*/
|
|
||||||
protected void configureMessageListener(MessageConsumer consumer) throws JMSException {
|
|
||||||
final MessageConsumer fConsumer = consumer;
|
|
||||||
|
|
||||||
consumer.setMessageListener(new MessageListener() {
|
|
||||||
@Override
|
|
||||||
public void onMessage(Message msg) {
|
|
||||||
LOG.debug("got a message on consumer {}", fConsumer);
|
|
||||||
messageReceived();
|
|
||||||
|
|
||||||
// Delay long enough for the consumer to get closed while this delay is active.
|
|
||||||
delay(3000, "pause so connection shutdown leads to unacked message redelivery");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a test message now.
|
|
||||||
*/
|
|
||||||
protected void sendMessage() throws JMSException {
|
|
||||||
Session sess = this.producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
|
||||||
MessageProducer prod = sess.createProducer(queue);
|
|
||||||
prod.send(sess.createTextMessage("X-TEST-MSG-X"));
|
|
||||||
prod.close();
|
|
||||||
sess.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the given connection safely and log any exception caught.
|
|
||||||
*/
|
|
||||||
protected void closeConnection(Connection conn) {
|
|
||||||
try {
|
|
||||||
conn.close();
|
|
||||||
} catch (JMSException jmsExc) {
|
|
||||||
LOG.info("failed to cleanup connection", jmsExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pause for the given length of time, in milliseconds, logging an interruption if one occurs. Don't try to
|
|
||||||
* recover from interrupt - the test case does not support interrupting and such an occurrence likely means the
|
|
||||||
* test is being aborted.
|
|
||||||
*/
|
|
||||||
protected void delay(long delayMs, String desc) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(delayMs);
|
|
||||||
} catch (InterruptedException intExc) {
|
|
||||||
LOG.warn("sleep interrupted: " + desc, intExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait up to the specified duration for a message to be received by any consumer.
|
|
||||||
*/
|
|
||||||
protected void waitForMessage(long delayMs) {
|
|
||||||
try {
|
|
||||||
synchronized (this.messageReceiveSync) {
|
|
||||||
while (this.receiveCount == 0) {
|
|
||||||
this.messageReceiveSync.wait(delayMs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (InterruptedException intExc) {
|
|
||||||
LOG.warn("sleep interrupted: wait for message to arrive");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,433 +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.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* 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.broker.region;
|
|
||||||
|
|
||||||
import javax.jms.InvalidSelectorException;
|
|
||||||
import javax.management.ObjectName;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.activemq.broker.BrokerService;
|
|
||||||
import org.apache.activemq.broker.ConnectionContext;
|
|
||||||
import org.apache.activemq.broker.ProducerBrokerExchange;
|
|
||||||
import org.apache.activemq.command.ActiveMQDestination;
|
|
||||||
import org.apache.activemq.command.ActiveMQMessage;
|
|
||||||
import org.apache.activemq.command.ActiveMQQueue;
|
|
||||||
import org.apache.activemq.command.ConsumerInfo;
|
|
||||||
import org.apache.activemq.command.Message;
|
|
||||||
import org.apache.activemq.command.MessageAck;
|
|
||||||
import org.apache.activemq.command.MessageDispatchNotification;
|
|
||||||
import org.apache.activemq.command.MessageId;
|
|
||||||
import org.apache.activemq.command.MessagePull;
|
|
||||||
import org.apache.activemq.command.ProducerInfo;
|
|
||||||
import org.apache.activemq.command.Response;
|
|
||||||
import org.apache.activemq.filter.MessageEvaluationContext;
|
|
||||||
import org.apache.activemq.state.ProducerState;
|
|
||||||
import org.apache.activemq.store.MessageStore;
|
|
||||||
import org.apache.activemq.thread.TaskRunnerFactory;
|
|
||||||
|
|
||||||
public class SubscriptionAddRemoveQueueTest extends TestCase {
|
|
||||||
|
|
||||||
Queue queue;
|
|
||||||
|
|
||||||
ConsumerInfo info = new ConsumerInfo();
|
|
||||||
List<SimpleImmediateDispatchSubscription> subs = new ArrayList<>();
|
|
||||||
ConnectionContext context = new ConnectionContext();
|
|
||||||
ProducerBrokerExchange producerBrokerExchange = new ProducerBrokerExchange();
|
|
||||||
ProducerInfo producerInfo = new ProducerInfo();
|
|
||||||
ProducerState producerState = new ProducerState(producerInfo);
|
|
||||||
ActiveMQDestination destination = new ActiveMQQueue("TEST");
|
|
||||||
int numSubscriptions = 1000;
|
|
||||||
boolean working = true;
|
|
||||||
int senders = 20;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
BrokerService brokerService = new BrokerService();
|
|
||||||
brokerService.start();
|
|
||||||
DestinationStatistics parentStats = new DestinationStatistics();
|
|
||||||
parentStats.setEnabled(true);
|
|
||||||
|
|
||||||
TaskRunnerFactory taskFactory = new TaskRunnerFactory();
|
|
||||||
MessageStore store = null;
|
|
||||||
|
|
||||||
info.setDestination(destination);
|
|
||||||
info.setPrefetchSize(100);
|
|
||||||
|
|
||||||
producerBrokerExchange.setProducerState(producerState);
|
|
||||||
producerBrokerExchange.setConnectionContext(context);
|
|
||||||
|
|
||||||
queue = new Queue(brokerService, destination, store, parentStats, taskFactory);
|
|
||||||
queue.initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testNoDispatchToRemovedConsumers() throws Exception {
|
|
||||||
final AtomicInteger producerId = new AtomicInteger();
|
|
||||||
Runnable sender = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
AtomicInteger id = new AtomicInteger();
|
|
||||||
int producerIdAndIncrement = producerId.getAndIncrement();
|
|
||||||
while (working) {
|
|
||||||
try {
|
|
||||||
Message msg = new ActiveMQMessage();
|
|
||||||
msg.setDestination(destination);
|
|
||||||
msg.setMessageId(new MessageId(producerIdAndIncrement + ":0:" + id.getAndIncrement()));
|
|
||||||
queue.send(producerBrokerExchange, msg);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
fail("unexpected exception in sendMessage, ex:" + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Runnable subRemover = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (Subscription sub : subs) {
|
|
||||||
try {
|
|
||||||
queue.removeSubscription(context, sub, 0);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
fail("unexpected exception in removeSubscription, ex:" + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < numSubscriptions; i++) {
|
|
||||||
SimpleImmediateDispatchSubscription sub = new SimpleImmediateDispatchSubscription();
|
|
||||||
subs.add(sub);
|
|
||||||
queue.addSubscription(context, sub);
|
|
||||||
}
|
|
||||||
assertEquals("there are X subscriptions", numSubscriptions, queue.getDestinationStatistics().getConsumers().getCount());
|
|
||||||
ExecutorService executor = Executors.newCachedThreadPool();
|
|
||||||
for (int i = 0; i < senders; i++) {
|
|
||||||
executor.submit(sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread.sleep(1000);
|
|
||||||
for (SimpleImmediateDispatchSubscription sub : subs) {
|
|
||||||
assertTrue("There are some locked messages in the subscription", hasSomeLocks(sub.dispatched));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<?> result = executor.submit(subRemover);
|
|
||||||
result.get();
|
|
||||||
working = false;
|
|
||||||
assertEquals("there are no subscriptions", 0, queue.getDestinationStatistics().getConsumers().getCount());
|
|
||||||
|
|
||||||
for (SimpleImmediateDispatchSubscription sub : subs) {
|
|
||||||
assertTrue("There are no locked messages in any removed subscriptions", !hasSomeLocks(sub.dispatched));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasSomeLocks(List<MessageReference> dispatched) {
|
|
||||||
boolean hasLock = false;
|
|
||||||
for (MessageReference mr : dispatched) {
|
|
||||||
QueueMessageReference qmr = (QueueMessageReference) mr;
|
|
||||||
if (qmr.getLockOwner() != null) {
|
|
||||||
hasLock = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hasLock;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SimpleImmediateDispatchSubscription implements Subscription, LockOwner {
|
|
||||||
|
|
||||||
private SubscriptionStatistics subscriptionStatistics = new SubscriptionStatistics();
|
|
||||||
List<MessageReference> dispatched = Collections.synchronizedList(new ArrayList<MessageReference>());
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getPendingMessageSize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void acknowledge(ConnectionContext context, MessageAck ack) throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void add(MessageReference node) throws Exception {
|
|
||||||
// immediate dispatch
|
|
||||||
QueueMessageReference qmr = (QueueMessageReference) node;
|
|
||||||
qmr.lock(this);
|
|
||||||
dispatched.add(qmr);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConnectionContext getContext() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCursorMemoryHighWaterMark() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCursorMemoryHighWaterMark(int cursorMemoryHighWaterMark) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSlowConsumer() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unmatched(MessageReference node) throws IOException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getTimeOfLastMessageAck() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getConsumedCount() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void incrementConsumedCount() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resetConsumedCount() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void add(ConnectionContext context, Destination destination) throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void gc() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConsumerInfo getConsumerInfo() {
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getDequeueCounter() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getDispatchedCounter() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getDispatchedQueueSize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getEnqueueCounter() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getInFlightSize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getInFlightUsage() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ObjectName getObjectName() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPendingQueueSize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPrefetchSize() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSelector() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBrowser() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isFull() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isHighWaterMark() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLowWaterMark() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRecoveryRequired() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSlave() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(MessageReference node, MessageEvaluationContext context) throws IOException {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(ActiveMQDestination destination) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void processMessageDispatchNotification(MessageDispatchNotification mdn) throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Response pullMessage(ConnectionContext context, MessagePull pull) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isWildcard() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<MessageReference> remove(ConnectionContext context, Destination destination) throws Exception {
|
|
||||||
return new ArrayList<>(dispatched);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setObjectName(ObjectName objectName) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSelector(String selector) throws InvalidSelectorException, UnsupportedOperationException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateConsumerPrefetch(int newPrefetch) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addRecoveredMessage(ConnectionContext context, MessageReference message) throws Exception {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ActiveMQDestination getActiveMQDestination() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLockPriority() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLockExclusive() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addDestination(Destination destination) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeDestination(Destination destination) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int countBeforeFull() {
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SubscriptionStatistics getSubscriptionStatistics() {
|
|
||||||
return subscriptionStatistics;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getInFlightMessageSize() {
|
|
||||||
return subscriptionStatistics.getInflightMessageSize().getTotalSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue