This closes #8 ActiveMQ5 tests
This commit is contained in:
commit
7ee0f559c6
|
@ -647,9 +647,10 @@ public class OpenWireMessageConverter implements MessageConverter
|
|||
amqMsg.setDestination(dest);
|
||||
}
|
||||
|
||||
String groupId = (String) coreMessage.getObjectProperty(AMQ_MSG_GROUP_ID);
|
||||
if (groupId != null)
|
||||
Object value = coreMessage.getObjectProperty(AMQ_MSG_GROUP_ID);
|
||||
if (value != null)
|
||||
{
|
||||
String groupId = value.toString();
|
||||
amqMsg.setGroupID(groupId);
|
||||
}
|
||||
|
||||
|
|
7
pom.xml
7
pom.xml
|
@ -70,6 +70,7 @@
|
|||
<skipPerformanceTests>true</skipPerformanceTests>
|
||||
<skipConcurrentTests>true</skipConcurrentTests>
|
||||
<skipRestTests>true</skipRestTests>
|
||||
<skipActiveMQ5Tests>true</skipActiveMQ5Tests>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
||||
|
@ -949,6 +950,12 @@
|
|||
<exclude>**/org/apache/activemq/artemis/utils/json/**</exclude>
|
||||
<exclude>**/org/apache/activemq/artemis/utils/Base64.java</exclude>
|
||||
<exclude>ratReport.txt</exclude>
|
||||
<!-- activemq5 unit tests exclude -->
|
||||
<exclude>**/*.data</exclude>
|
||||
<exclude>**/*.bin</exclude>
|
||||
<exclude>**/src/test/resources/keystore</exclude>
|
||||
<exclude>**/*.log</exclude>
|
||||
<exclude>**/*.redo</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
<executions>
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# ActiveMQ 5 unit tests against ActiveMQ Artemis wrapper
|
||||
|
||||
|
||||
This maven module is used to run ActiveMQ5 unit tests against
|
||||
ActiveMQ Artemis broker.
|
||||
|
||||
The Artemis broker is 'wrapped' in BrokerService and the unit
|
||||
tests are slightly modified.
|
||||
|
||||
Then run the tests simply do
|
||||
|
||||
```mvn -DskipActiveMQTests=false clean test```
|
||||
|
||||
It will kickoff the whole test suite.
|
||||
|
|
@ -0,0 +1,387 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.apache.activemq.tests</groupId>
|
||||
<artifactId>artemis-tests-pom</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>activemq5-unit-tests</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>ActiveMQ5.x unit tests</name>
|
||||
|
||||
<properties>
|
||||
<activemq.basedir>${project.basedir}/../..</activemq.basedir>
|
||||
<activemq5.project.version>5.11.1</activemq5.project.version>
|
||||
<jmdns-version>3.4.1</jmdns-version>
|
||||
<ftpserver-version>1.0.6</ftpserver-version>
|
||||
<jmock-version>2.5.1</jmock-version>
|
||||
<spring-version>3.2.11.RELEASE</spring-version>
|
||||
<org-apache-derby-version>10.11.1.1</org-apache-derby-version>
|
||||
<commons-io-version>2.4</commons-io-version>
|
||||
<commons-net-version>3.3</commons-net-version>
|
||||
<qpid-jms-version>0.30</qpid-jms-version>
|
||||
<xbean-version>3.18</xbean-version>
|
||||
<hamcrest-version>1.3</hamcrest-version>
|
||||
<slf4j-version>1.7.10</slf4j-version>
|
||||
<jasypt-version>1.9.2</jasypt-version>
|
||||
<directory-version>2.0.0-M6</directory-version>
|
||||
<activeio-core-version>3.1.4</activeio-core-version>
|
||||
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-client</artifactId>
|
||||
<version>${activemq5.project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-jaas</artifactId>
|
||||
<version>${activemq5.project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-broker</artifactId>
|
||||
<version>${activemq5.project.version}</version>
|
||||
<type>test-jar</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-jdbc-store</artifactId>
|
||||
<version>${activemq5.project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-kahadb-store</artifactId>
|
||||
<version>${activemq5.project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-leveldb-store</artifactId>
|
||||
<version>${activemq5.project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-pool</artifactId>
|
||||
<version>${activemq5.project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-spring</artifactId>
|
||||
<version>${activemq5.project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-partition</artifactId>
|
||||
<version>${activemq5.project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-stomp</artifactId>
|
||||
<version>${activemq5.project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-console</artifactId>
|
||||
<version>${activemq5.project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activeio-core</artifactId>
|
||||
<version>${activeio-core-version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.osgi</groupId>
|
||||
<artifactId>org.osgi.core</artifactId>
|
||||
<version>4.3.1</version>
|
||||
</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>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derby</artifactId>
|
||||
<version>${org-apache-derby-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-net</groupId>
|
||||
<artifactId>commons-net</artifactId>
|
||||
<version>${commons-net-version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.qpid</groupId>
|
||||
<artifactId>qpid-amqp-1-0-client-jms</artifactId>
|
||||
<version>${qpid-jms-version}</version>
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<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>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15</artifactId>
|
||||
<version>1.46</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-server-integ</artifactId>
|
||||
<version>${directory-version}</version>
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
<version>1.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- artemis modules -->
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>artemis-commons</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>artemis-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>artemis-openwire-protocol</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.rat</groupId>
|
||||
<artifactId>apache-rat-plugin</artifactId>
|
||||
<version>0.11</version>
|
||||
<configuration>
|
||||
<reportFile>${activemq.basedir}/ratReport.txt</reportFile>
|
||||
<skip>${skipLicenseCheck}</skip>
|
||||
<excludes>
|
||||
<exclude>**/*.data</exclude>
|
||||
<exclude>**/*.bin</exclude>
|
||||
<exclude>**/*.log</exclude>
|
||||
<exclude>**/*.redo</exclude>
|
||||
<exclude>**/src/test/resources/keystore</exclude>
|
||||
<exclude>**/META-INF/services/*</exclude>
|
||||
<exclude>**/*/*.txt</exclude>
|
||||
<exclude>**/*.md</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>2.12</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
<inherited>true</inherited>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-Activator>org.apache.activemq.util.osgi.Activator</Bundle-Activator>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>${skipActiveMQ5Tests}</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* 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.artemiswrapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
|
||||
public class ArtemisBrokerHelper {
|
||||
|
||||
private static volatile Object service = null;
|
||||
private static Class<?> serviceClass;
|
||||
|
||||
static {
|
||||
try {
|
||||
serviceClass = Class.forName("org.apache.activemq.broker.BrokerService");
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
// start a tcp transport artemis broker, the broker need to
|
||||
// be invm with client.
|
||||
public static void startArtemisBroker(URI location) throws IOException {
|
||||
if (service != null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
service = serviceClass.newInstance();
|
||||
Method startMethod = serviceClass.getMethod("start");
|
||||
startMethod.invoke(service, (Object[]) null);
|
||||
} catch (InstantiationException e) {
|
||||
throw new IOException("Inst exception", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IOException("IllegalAccess exception ", e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new IOException("Nosuchmethod", e);
|
||||
} catch (SecurityException e) {
|
||||
throw new IOException("Security exception", e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IOException("IllegalArgumentException exception", e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new IOException("InvocationTargetException exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void makeSureDestinationExists(ActiveMQDestination activemqDestination) throws Exception {
|
||||
Method startMethod = serviceClass.getMethod("makeSureDestinationExists", ActiveMQDestination.class);
|
||||
startMethod.invoke(service, activemqDestination);
|
||||
}
|
||||
|
||||
//some tests run broker in setUp(). This need be called
|
||||
//to prevent auto broker creation.
|
||||
public static void setBroker(Object startedBroker) {
|
||||
service = startedBroker;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,811 @@
|
|||
/**
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.RejectedExecutionHandler;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionMetaData;
|
||||
import org.apache.activemq.ConfigurationException;
|
||||
import org.apache.activemq.Service;
|
||||
import org.apache.activemq.advisory.AdvisoryBroker;
|
||||
import org.apache.activemq.broker.artemiswrapper.ArtemisBrokerWrapper;
|
||||
import org.apache.activemq.broker.cluster.ConnectionSplitBroker;
|
||||
import org.apache.activemq.broker.jmx.AnnotatedMBean;
|
||||
import org.apache.activemq.broker.jmx.BrokerMBeanSupport;
|
||||
import org.apache.activemq.broker.jmx.BrokerView;
|
||||
import org.apache.activemq.broker.jmx.ConnectorView;
|
||||
import org.apache.activemq.broker.jmx.ConnectorViewMBean;
|
||||
import org.apache.activemq.broker.jmx.HealthView;
|
||||
import org.apache.activemq.broker.jmx.HealthViewMBean;
|
||||
import org.apache.activemq.broker.jmx.JmsConnectorView;
|
||||
import org.apache.activemq.broker.jmx.JobSchedulerView;
|
||||
import org.apache.activemq.broker.jmx.JobSchedulerViewMBean;
|
||||
import org.apache.activemq.broker.jmx.Log4JConfigView;
|
||||
import org.apache.activemq.broker.jmx.ManagedRegionBroker;
|
||||
import org.apache.activemq.broker.jmx.ManagementContext;
|
||||
import org.apache.activemq.broker.jmx.NetworkConnectorView;
|
||||
import org.apache.activemq.broker.jmx.NetworkConnectorViewMBean;
|
||||
import org.apache.activemq.broker.jmx.ProxyConnectorView;
|
||||
import org.apache.activemq.broker.region.CompositeDestinationInterceptor;
|
||||
import org.apache.activemq.broker.region.Destination;
|
||||
import org.apache.activemq.broker.region.DestinationFactory;
|
||||
import org.apache.activemq.broker.region.DestinationFactoryImpl;
|
||||
import org.apache.activemq.broker.region.DestinationInterceptor;
|
||||
import org.apache.activemq.broker.region.RegionBroker;
|
||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
||||
import org.apache.activemq.broker.region.virtual.MirroredQueue;
|
||||
import org.apache.activemq.broker.region.virtual.VirtualDestination;
|
||||
import org.apache.activemq.broker.region.virtual.VirtualDestinationInterceptor;
|
||||
import org.apache.activemq.broker.region.virtual.VirtualTopic;
|
||||
import org.apache.activemq.broker.scheduler.JobSchedulerStore;
|
||||
import org.apache.activemq.broker.scheduler.SchedulerBroker;
|
||||
import org.apache.activemq.broker.scheduler.memory.InMemoryJobSchedulerStore;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.BrokerId;
|
||||
import org.apache.activemq.command.ProducerInfo;
|
||||
import org.apache.activemq.filter.DestinationFilter;
|
||||
import org.apache.activemq.network.ConnectionFilter;
|
||||
import org.apache.activemq.network.DiscoveryNetworkConnector;
|
||||
import org.apache.activemq.network.NetworkConnector;
|
||||
import org.apache.activemq.network.jms.JmsConnector;
|
||||
import org.apache.activemq.openwire.OpenWireFormat;
|
||||
import org.apache.activemq.proxy.ProxyConnector;
|
||||
import org.apache.activemq.security.MessageAuthorizationPolicy;
|
||||
import org.apache.activemq.selector.SelectorParser;
|
||||
import org.apache.activemq.store.JournaledStore;
|
||||
import org.apache.activemq.store.PListStore;
|
||||
import org.apache.activemq.store.PersistenceAdapter;
|
||||
import org.apache.activemq.store.PersistenceAdapterFactory;
|
||||
import org.apache.activemq.store.memory.MemoryPersistenceAdapter;
|
||||
import org.apache.activemq.thread.Scheduler;
|
||||
import org.apache.activemq.thread.TaskRunnerFactory;
|
||||
import org.apache.activemq.transport.TransportFactorySupport;
|
||||
import org.apache.activemq.transport.TransportServer;
|
||||
import org.apache.activemq.transport.vm.VMTransportFactory;
|
||||
import org.apache.activemq.usage.SystemUsage;
|
||||
import org.apache.activemq.util.BrokerSupport;
|
||||
import org.apache.activemq.util.DefaultIOExceptionHandler;
|
||||
import org.apache.activemq.util.IOExceptionHandler;
|
||||
import org.apache.activemq.util.IOExceptionSupport;
|
||||
import org.apache.activemq.util.IOHelper;
|
||||
import org.apache.activemq.util.InetAddressUtil;
|
||||
import org.apache.activemq.util.ServiceStopper;
|
||||
import org.apache.activemq.util.ThreadPoolUtils;
|
||||
import org.apache.activemq.util.TimeUtils;
|
||||
import org.apache.activemq.util.URISupport;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
/**
|
||||
* Manages the life-cycle of an ActiveMQ Broker. A BrokerService consists of a
|
||||
* number of transport connectors, network connectors and a bunch of properties
|
||||
* which can be used to configure the broker as its lazily created.
|
||||
*
|
||||
* @org.apache.xbean.XBean
|
||||
*/
|
||||
public class BrokerService implements Service
|
||||
{
|
||||
public static final String DEFAULT_PORT = "61616";
|
||||
public static final String DEFAULT_BROKER_NAME = "localhost";
|
||||
public static final String BROKER_VERSION;
|
||||
public static final int DEFAULT_MAX_FILE_LENGTH = 1024 * 1024 * 32;
|
||||
public static final long DEFAULT_START_TIMEOUT = 600000L;
|
||||
|
||||
public String SERVER_SIDE_KEYSTORE;
|
||||
public String KEYSTORE_PASSWORD;
|
||||
public String SERVER_SIDE_TRUSTSTORE;
|
||||
public String TRUSTSTORE_PASSWORD;
|
||||
public String storeType;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BrokerService.class);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final long serialVersionUID = 7353129142305630237L;
|
||||
|
||||
private String brokerName = DEFAULT_BROKER_NAME;
|
||||
private Broker broker;
|
||||
private BrokerId brokerId;
|
||||
private Throwable startException = null;
|
||||
private boolean startAsync = false;
|
||||
public Set<Integer> extraConnectors = new HashSet<Integer>();
|
||||
private File dataDirectoryFile;
|
||||
|
||||
static
|
||||
{
|
||||
InputStream in;
|
||||
String version = null;
|
||||
if ((in = BrokerService.class.getResourceAsStream("/org/apache/activemq/version.txt")) != null)
|
||||
{
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||
try
|
||||
{
|
||||
version = reader.readLine();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
BROKER_VERSION = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "BrokerService[" + getBrokerName() + "]";
|
||||
}
|
||||
|
||||
private String getBrokerVersion()
|
||||
{
|
||||
String version = ActiveMQConnectionMetaData.PROVIDER_VERSION;
|
||||
if (version == null)
|
||||
{
|
||||
version = BROKER_VERSION;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void start() throws Exception
|
||||
{
|
||||
startBroker(startAsync);
|
||||
}
|
||||
|
||||
private void startBroker(boolean async) throws Exception
|
||||
{
|
||||
if (async)
|
||||
{
|
||||
new Thread("Broker Starting Thread")
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
doStartBroker();
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
startException = t;
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
doStartBroker();
|
||||
}
|
||||
}
|
||||
|
||||
private void doStartBroker() throws Exception
|
||||
{
|
||||
if (startException != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
broker = getBroker();
|
||||
brokerId = broker.getBrokerId();
|
||||
|
||||
LOG.info("Apache ActiveMQ Artemis Wrapper {} ({}, {}) is starting", new Object[]{getBrokerVersion(), getBrokerName(), brokerId});
|
||||
|
||||
try
|
||||
{
|
||||
broker.start();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new Exception(t);
|
||||
}
|
||||
|
||||
LOG.info("Apache ActiveMQ Artemis Wrapper {} ({}, {}) started", new Object[]{getBrokerVersion(), getBrokerName(), brokerId});
|
||||
LOG.info("For help or more information please see: http://activemq.apache.org");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* @org.apache .xbean.DestroyMethod
|
||||
*/
|
||||
@Override
|
||||
public void stop() throws Exception
|
||||
{
|
||||
|
||||
LOG.info("Apache ActiveMQ Artemis{} ({}, {}) is shutting down", new Object[]{getBrokerVersion(), getBrokerName(), brokerId});
|
||||
|
||||
if (broker != null)
|
||||
{
|
||||
broker.stop();
|
||||
broker = null;
|
||||
}
|
||||
LOG.info("Apache ActiveMQ Artemis {} ({}, {}) is shutdown", new Object[]{getBrokerVersion(), getBrokerName(), brokerId});
|
||||
}
|
||||
|
||||
// Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the message broker
|
||||
*/
|
||||
public Broker getBroker() throws Exception
|
||||
{
|
||||
if (broker == null)
|
||||
{
|
||||
broker = createBroker();
|
||||
}
|
||||
return broker;
|
||||
}
|
||||
|
||||
public String getBrokerName()
|
||||
{
|
||||
return brokerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of this broker; which must be unique in the network
|
||||
*
|
||||
* @param brokerName
|
||||
*/
|
||||
public void setBrokerName(String brokerName)
|
||||
{
|
||||
if (brokerName == null)
|
||||
{
|
||||
throw new NullPointerException("The broker name cannot be null");
|
||||
}
|
||||
String str = brokerName.replaceAll("[^a-zA-Z0-9\\.\\_\\-\\:]", "_");
|
||||
if (!str.equals(brokerName))
|
||||
{
|
||||
LOG.error("Broker Name: {} contained illegal characters - replaced with {}", brokerName, str);
|
||||
}
|
||||
this.brokerName = str.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create a new broker
|
||||
*
|
||||
* @throws Exception
|
||||
* @throws
|
||||
* @throws
|
||||
*/
|
||||
protected Broker createBroker() throws Exception
|
||||
{
|
||||
broker = createBrokerWrapper();
|
||||
return broker;
|
||||
}
|
||||
|
||||
private Broker createBrokerWrapper()
|
||||
{
|
||||
return new ArtemisBrokerWrapper(this);
|
||||
}
|
||||
|
||||
public void makeSureDestinationExists(ActiveMQDestination activemqDestination) throws Exception
|
||||
{
|
||||
System.out.println(">>>> making sure dest exits: " + activemqDestination);
|
||||
ArtemisBrokerWrapper hqBroker = (ArtemisBrokerWrapper) this.broker;
|
||||
//it can be null
|
||||
if (activemqDestination == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (activemqDestination.isQueue())
|
||||
{
|
||||
String qname = activemqDestination.getPhysicalName();
|
||||
System.out.println("physical name: " + qname);
|
||||
hqBroker.makeSureQueueExists(qname);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean enableSsl()
|
||||
{
|
||||
return this.SERVER_SIDE_KEYSTORE != null;
|
||||
}
|
||||
|
||||
//below are methods called directly by tests
|
||||
//we don't actually implement any of these for now,
|
||||
//just to make test compile pass.
|
||||
|
||||
//we may get class cast exception as in TestSupport it
|
||||
//casts the broker to RegionBroker, which we didn't
|
||||
//implement (wrap) yet. Consider solving it later.
|
||||
public Broker getRegionBroker()
|
||||
{
|
||||
return broker;
|
||||
}
|
||||
|
||||
public void setPersistenceAdapter(PersistenceAdapter persistenceAdapter) throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
public File getDataDirectoryFile()
|
||||
{
|
||||
if (dataDirectoryFile == null)
|
||||
{
|
||||
dataDirectoryFile = new File(IOHelper.getDefaultDataDirectory());
|
||||
}
|
||||
return dataDirectoryFile;
|
||||
}
|
||||
|
||||
public File getBrokerDataDirectory()
|
||||
{
|
||||
String brokerDir = getBrokerName();
|
||||
return new File(getDataDirectoryFile(), brokerDir);
|
||||
}
|
||||
|
||||
public PersistenceAdapter getPersistenceAdapter() throws IOException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void waitUntilStopped()
|
||||
{
|
||||
}
|
||||
|
||||
public boolean waitUntilStarted()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setDestinationPolicy(PolicyMap policyMap)
|
||||
{
|
||||
}
|
||||
|
||||
public void setDeleteAllMessagesOnStartup(boolean deletePersistentMessagesOnStartup)
|
||||
{
|
||||
}
|
||||
|
||||
public void setUseJmx(boolean useJmx)
|
||||
{
|
||||
}
|
||||
|
||||
public ManagementContext getManagementContext()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public BrokerView getAdminView() throws Exception
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<TransportConnector> getTransportConnectors()
|
||||
{
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public TransportConnector addConnector(String bindAddress) throws Exception
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setIoExceptionHandler(IOExceptionHandler ioExceptionHandler)
|
||||
{
|
||||
}
|
||||
|
||||
public void setPersistent(boolean persistent)
|
||||
{
|
||||
}
|
||||
|
||||
public boolean isSlave()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public Destination getDestination(ActiveMQDestination destination) throws Exception
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setAllowTempAutoCreationOnSend(boolean allowTempAutoCreationOnSend)
|
||||
{
|
||||
}
|
||||
|
||||
public void setDedicatedTaskRunner(boolean dedicatedTaskRunner)
|
||||
{
|
||||
}
|
||||
|
||||
public void setAdvisorySupport(boolean advisorySupport)
|
||||
{
|
||||
}
|
||||
|
||||
public void setUseShutdownHook(boolean useShutdownHook)
|
||||
{
|
||||
}
|
||||
|
||||
public void deleteAllMessages() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
public Service[] getServices()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setPopulateUserNameInMBeans(boolean value)
|
||||
{
|
||||
}
|
||||
|
||||
public void setDestinations(ActiveMQDestination[] destinations)
|
||||
{
|
||||
}
|
||||
|
||||
public URI getVmConnectorURI()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public SystemUsage getSystemUsage()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized PListStore getTempDataStore()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setJmsBridgeConnectors(JmsConnector[] jmsConnectors)
|
||||
{
|
||||
}
|
||||
|
||||
public void setDestinationInterceptors(DestinationInterceptor[] destinationInterceptors)
|
||||
{
|
||||
}
|
||||
|
||||
public SslContext getSslContext()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setDataDirectory(String dataDirectory)
|
||||
{
|
||||
}
|
||||
|
||||
public void setPlugins(BrokerPlugin[] plugins)
|
||||
{
|
||||
}
|
||||
|
||||
public void setKeepDurableSubsActive(boolean keepDurableSubsActive)
|
||||
{
|
||||
}
|
||||
|
||||
public NetworkConnector addNetworkConnector(String discoveryAddress) throws Exception
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public TransportConnector getConnectorByName(String connectorName)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public TransportConnector addConnector(TransportConnector connector) throws Exception
|
||||
{
|
||||
return connector;
|
||||
}
|
||||
|
||||
public void setEnableStatistics(boolean enableStatistics)
|
||||
{
|
||||
}
|
||||
|
||||
public void setSystemUsage(SystemUsage memoryManager)
|
||||
{
|
||||
}
|
||||
|
||||
public void setManagementContext(ManagementContext managementContext)
|
||||
{
|
||||
}
|
||||
|
||||
public void setSchedulerDirectoryFile(File schedulerDirectory)
|
||||
{
|
||||
}
|
||||
|
||||
public List<NetworkConnector> getNetworkConnectors()
|
||||
{
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public void setSchedulerSupport(boolean schedulerSupport)
|
||||
{
|
||||
}
|
||||
|
||||
public void setPopulateJMSXUserID(boolean populateJMSXUserID)
|
||||
{
|
||||
}
|
||||
|
||||
public boolean isUseJmx()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isPersistent()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public TransportConnector getTransportConnectorByScheme(String scheme)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public TaskRunnerFactory getTaskRunnerFactory()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isStarted()
|
||||
{
|
||||
if (broker == null) return false;
|
||||
return !broker.isStopped();
|
||||
}
|
||||
|
||||
public ProxyConnector addProxyConnector(ProxyConnector connector) throws Exception
|
||||
{
|
||||
return connector;
|
||||
}
|
||||
|
||||
public void setDataDirectoryFile(File dataDirectoryFile)
|
||||
{
|
||||
this.dataDirectoryFile = dataDirectoryFile;
|
||||
}
|
||||
|
||||
public PolicyMap getDestinationPolicy()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setTransportConnectorURIs(String[] transportConnectorURIs)
|
||||
{
|
||||
}
|
||||
|
||||
public boolean isPopulateJMSXUserID()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public NetworkConnector getNetworkConnectorByName(String connectorName)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean removeNetworkConnector(NetworkConnector connector)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setTransportConnectors(List<TransportConnector> transportConnectors) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
public NetworkConnector addNetworkConnector(NetworkConnector connector) throws Exception
|
||||
{
|
||||
return connector;
|
||||
}
|
||||
|
||||
public void setTempDataStore(PListStore tempDataStore)
|
||||
{
|
||||
}
|
||||
|
||||
public void setJobSchedulerStore(JobSchedulerStore jobSchedulerStore)
|
||||
{
|
||||
}
|
||||
|
||||
public ObjectName getBrokerObjectName() throws MalformedObjectNameException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public TransportConnector addConnector(URI bindAddress) throws Exception
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setCacheTempDestinations(boolean cacheTempDestinations)
|
||||
{
|
||||
}
|
||||
|
||||
public void setOfflineDurableSubscriberTimeout(long offlineDurableSubscriberTimeout)
|
||||
{
|
||||
}
|
||||
|
||||
public void setOfflineDurableSubscriberTaskSchedule(long offlineDurableSubscriberTaskSchedule)
|
||||
{
|
||||
}
|
||||
|
||||
public boolean isStopped()
|
||||
{
|
||||
return broker.isStopped();
|
||||
}
|
||||
|
||||
public void setBrokerId(String brokerId)
|
||||
{
|
||||
}
|
||||
|
||||
public BrokerPlugin[] getPlugins()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void stopAllConnectors(ServiceStopper stopper)
|
||||
{
|
||||
}
|
||||
|
||||
public void setMessageAuthorizationPolicy(MessageAuthorizationPolicy messageAuthorizationPolicy)
|
||||
{
|
||||
}
|
||||
|
||||
public void setNetworkConnectorStartAsync(boolean networkConnectorStartAsync)
|
||||
{
|
||||
}
|
||||
|
||||
public boolean isRestartAllowed()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setTaskRunnerFactory(TaskRunnerFactory taskRunnerFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public void start(boolean force) throws Exception
|
||||
{
|
||||
this.start();
|
||||
}
|
||||
|
||||
public void setMonitorConnectionSplits(boolean monitorConnectionSplits)
|
||||
{
|
||||
}
|
||||
|
||||
public void setUseMirroredQueues(boolean useMirroredQueues)
|
||||
{
|
||||
}
|
||||
|
||||
public File getTmpDataDirectory()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isUseShutdownHook()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isDeleteAllMessagesOnStartup()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setUseVirtualTopics(boolean useVirtualTopics)
|
||||
{
|
||||
}
|
||||
|
||||
public boolean isUseLoggingForShutdownErrors()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public TransportConnector addConnector(TransportServer transport) throws Exception
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized JobSchedulerStore getJobSchedulerStore()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean removeConnector(TransportConnector connector) throws Exception
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public ConnectionContext getAdminConnectionContext() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setUseAuthenticatedPrincipalForJMSXUserID(boolean useAuthenticatedPrincipalForJMSXUserID)
|
||||
{
|
||||
}
|
||||
|
||||
public void setSchedulePeriodForDestinationPurge(int schedulePeriodForDestinationPurge)
|
||||
{
|
||||
}
|
||||
|
||||
public void setMbeanInvocationTimeout(long mbeanInvocationTimeout)
|
||||
{
|
||||
}
|
||||
|
||||
public void setNetworkConnectors(List<?> networkConnectors) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
public void removeDestination(ActiveMQDestination destination) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
public void setMaxPurgedDestinationsPerSweep(int maxPurgedDestinationsPerSweep)
|
||||
{
|
||||
}
|
||||
|
||||
public void setBrokerObjectName(ObjectName brokerObjectName)
|
||||
{
|
||||
}
|
||||
|
||||
public Map<String, String> getTransportConnectorURIsAsMap()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setSslContext(SslContext sslContext)
|
||||
{
|
||||
}
|
||||
|
||||
public void setPersistenceFactory(PersistenceAdapterFactory persistenceFactory)
|
||||
{
|
||||
}
|
||||
|
||||
protected TransportConnector createTransportConnector(URI brokerURI) throws Exception
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* 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.transport.TransportFactorySupport;
|
||||
import org.apache.activemq.transport.TransportServer;
|
||||
import org.apache.activemq.transport.tcp.SslTransportFactory;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* A BrokerService that allows access to the key and trust managers used by SSL
|
||||
* connections. There is no reason to use this class unless SSL is being used
|
||||
* AND the key and trust managers need to be specified from within code. In
|
||||
* fact, if the URI passed to this class does not have an "ssl" scheme, this
|
||||
* class will pass all work on to its superclass.
|
||||
*
|
||||
* @author sepandm@gmail.com (Sepand)
|
||||
*/
|
||||
public class SslBrokerService extends BrokerService
|
||||
{
|
||||
|
||||
public TransportConnector addSslConnector(String bindAddress, KeyManager[] km, TrustManager[] tm, SecureRandom random) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
public TransportConnector addSslConnector(URI bindAddress, KeyManager[] km, TrustManager[] tm, SecureRandom random) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected TransportServer createSslTransportServer(URI brokerURI, KeyManager[] km, TrustManager[] tm, SecureRandom random) throws IOException, KeyManagementException {
|
||||
return null;
|
||||
}
|
||||
|
||||
//one way
|
||||
public void setupSsl(String keystoreType, String password, String serverKeystore) {
|
||||
this.SERVER_SIDE_KEYSTORE = serverKeystore;
|
||||
this.KEYSTORE_PASSWORD = password;
|
||||
this.storeType = keystoreType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,674 @@
|
|||
/**
|
||||
* 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.artemiswrapper;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.TransportConfiguration;
|
||||
import org.apache.activemq.artemis.core.asyncio.impl.AsynchronousFileImpl;
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptorFactory;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServer;
|
||||
import org.apache.activemq.artemis.core.server.ActiveMQServers;
|
||||
import org.apache.activemq.artemis.core.server.JournalType;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.apache.activemq.broker.Broker;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.Connection;
|
||||
import org.apache.activemq.broker.ConnectionContext;
|
||||
import org.apache.activemq.broker.ConsumerBrokerExchange;
|
||||
import org.apache.activemq.broker.ProducerBrokerExchange;
|
||||
import org.apache.activemq.broker.region.Destination;
|
||||
import org.apache.activemq.broker.region.MessageReference;
|
||||
import org.apache.activemq.broker.region.Subscription;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.BrokerId;
|
||||
import org.apache.activemq.command.BrokerInfo;
|
||||
import org.apache.activemq.command.ConnectionInfo;
|
||||
import org.apache.activemq.command.ConsumerControl;
|
||||
import org.apache.activemq.command.ConsumerInfo;
|
||||
import org.apache.activemq.command.DestinationInfo;
|
||||
import org.apache.activemq.command.Message;
|
||||
import org.apache.activemq.command.MessageAck;
|
||||
import org.apache.activemq.command.MessageDispatch;
|
||||
import org.apache.activemq.command.MessageDispatchNotification;
|
||||
import org.apache.activemq.command.MessagePull;
|
||||
import org.apache.activemq.command.ProducerInfo;
|
||||
import org.apache.activemq.command.RemoveSubscriptionInfo;
|
||||
import org.apache.activemq.command.Response;
|
||||
import org.apache.activemq.command.SessionInfo;
|
||||
import org.apache.activemq.command.TransactionId;
|
||||
import org.apache.activemq.store.PListStore;
|
||||
import org.apache.activemq.thread.Scheduler;
|
||||
import org.apache.activemq.usage.Usage;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class ArtemisBrokerBase implements Broker {
|
||||
|
||||
private static final Logger LOG = LoggerFactory
|
||||
.getLogger(ArtemisBrokerBase.class);
|
||||
public static final String INVM_ACCEPTOR_FACTORY = InVMAcceptorFactory.class
|
||||
.getCanonicalName();
|
||||
|
||||
public static final String NETTY_ACCEPTOR_FACTORY = NettyAcceptorFactory.class
|
||||
.getCanonicalName();
|
||||
|
||||
public static final String NETTY_CONNECTOR_FACTORY = NettyConnectorFactory.class
|
||||
.getCanonicalName();
|
||||
|
||||
protected static final String CLUSTER_PASSWORD = "UnitTestsClusterPassword";
|
||||
|
||||
protected volatile boolean stopped;
|
||||
protected BrokerId brokerId = new BrokerId("Artemis Broker");
|
||||
protected BrokerService bservice;
|
||||
protected TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
protected String testDir;
|
||||
protected boolean realStore = false;
|
||||
|
||||
protected ActiveMQServer server;
|
||||
|
||||
protected boolean enableSecurity = false;
|
||||
|
||||
public ArtemisBrokerBase() {
|
||||
try {
|
||||
this.temporaryFolder.create();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public Destination addDestination(ConnectionContext context,
|
||||
ActiveMQDestination destination, boolean createIfTemporary)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDestination(ConnectionContext context,
|
||||
ActiveMQDestination destination, long timeout) throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ActiveMQDestination, Destination> getDestinationMap() {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Subscription addConsumer(ConnectionContext context, ConsumerInfo info)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeConsumer(ConnectionContext context, ConsumerInfo info)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSubscription(ConnectionContext context,
|
||||
RemoveSubscriptionInfo info) throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(ProducerBrokerExchange producerExchange, Message message)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acknowledge(ConsumerBrokerExchange consumerExchange,
|
||||
MessageAck ack) throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response messagePull(ConnectionContext context, MessagePull pull)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processDispatchNotification(
|
||||
MessageDispatchNotification messageDispatchNotification)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gc() {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Destination> getDestinations(ActiveMQDestination destination) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processConsumerControl(ConsumerBrokerExchange consumerExchange,
|
||||
ConsumerControl control) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reapplyInterceptor() {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Broker getAdaptor(Class type) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrokerId getBrokerId() {
|
||||
return brokerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBrokerName() {
|
||||
return "Artemis Broker";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBroker(Connection connection, BrokerInfo info) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeBroker(Connection connection, BrokerInfo info) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConnection(ConnectionContext context, ConnectionInfo info)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeConnection(ConnectionContext context,
|
||||
ConnectionInfo info, Throwable error) throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSession(ConnectionContext context, SessionInfo info)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSession(ConnectionContext context, SessionInfo info)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProducer(ConnectionContext context, ProducerInfo info)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeProducer(ConnectionContext context, ProducerInfo info)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection[] getClients() throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActiveMQDestination[] getDestinations() throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ActiveMQDestination, Destination> getDestinationMap(
|
||||
ActiveMQDestination destination) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransactionId[] getPreparedTransactions(ConnectionContext context)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginTransaction(ConnectionContext context, TransactionId xid)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int prepareTransaction(ConnectionContext context, TransactionId xid)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollbackTransaction(ConnectionContext context, TransactionId xid)
|
||||
throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitTransaction(ConnectionContext context, TransactionId xid,
|
||||
boolean onePhase) throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forgetTransaction(ConnectionContext context,
|
||||
TransactionId transactionId) throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrokerInfo[] getPeerBrokerInfos() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preProcessDispatch(MessageDispatch messageDispatch) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessDispatch(MessageDispatch messageDispatch) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStopped() {
|
||||
return stopped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ActiveMQDestination> getDurableDestinations() {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDestinationInfo(ConnectionContext context,
|
||||
DestinationInfo info) throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDestinationInfo(ConnectionContext context,
|
||||
DestinationInfo info) throws Exception {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFaultTolerantConfiguration() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionContext getAdminConnectionContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAdminConnectionContext(
|
||||
ConnectionContext adminConnectionContext) {
|
||||
//
|
||||
}
|
||||
|
||||
@Override
|
||||
public PListStore getTempDataStore() {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getVmConnectorURI() {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void brokerServiceStarted() {
|
||||
stopped = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrokerService getBrokerService() {
|
||||
return this.bservice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Broker getRoot() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpired(MessageReference messageReference) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageExpired(ConnectionContext context,
|
||||
MessageReference messageReference, Subscription subscription) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendToDeadLetterQueue(ConnectionContext context,
|
||||
MessageReference messageReference, Subscription subscription,
|
||||
Throwable poisonCause) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBrokerSequenceId() {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageConsumed(ConnectionContext context,
|
||||
MessageReference messageReference) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageDelivered(ConnectionContext context,
|
||||
MessageReference messageReference) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageDiscarded(ConnectionContext context, Subscription sub,
|
||||
MessageReference messageReference) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void slowConsumer(ConnectionContext context,
|
||||
Destination destination, Subscription subs) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fastProducer(ConnectionContext context,
|
||||
ProducerInfo producerInfo, ActiveMQDestination destination) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void isFull(ConnectionContext context, Destination destination,
|
||||
Usage usage) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nowMasterBroker() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scheduler getScheduler() {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThreadPoolExecutor getExecutor() {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void networkBridgeStarted(BrokerInfo brokerInfo,
|
||||
boolean createdByDuplex, String remoteIp) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void networkBridgeStopped(BrokerInfo brokerInfo) {
|
||||
throw new RuntimeException("Don't call me!");
|
||||
}
|
||||
|
||||
protected final ActiveMQServer createServer(final boolean realFiles,
|
||||
final boolean netty) throws Exception {
|
||||
return createServer(realFiles, createDefaultConfig(netty), -1, -1,
|
||||
new HashMap<String, AddressSettings>());
|
||||
}
|
||||
|
||||
protected final ActiveMQServer createServer(final boolean realFiles,
|
||||
final Configuration configuration, final int pageSize,
|
||||
final int maxAddressSize,
|
||||
final Map<String, AddressSettings> settings) {
|
||||
return createServer(realFiles, configuration, pageSize, maxAddressSize,
|
||||
AddressFullMessagePolicy.PAGE, settings);
|
||||
}
|
||||
|
||||
protected final ActiveMQServer createServer(final boolean realFiles,
|
||||
final Configuration configuration, final int pageSize,
|
||||
final int maxAddressSize,
|
||||
final AddressFullMessagePolicy fullPolicy,
|
||||
final Map<String, AddressSettings> settings) {
|
||||
ActiveMQServer server = ActiveMQServers.newActiveMQServer(configuration,
|
||||
realFiles);
|
||||
if (settings != null) {
|
||||
for (Map.Entry<String, AddressSettings> setting : settings
|
||||
.entrySet()) {
|
||||
server.getAddressSettingsRepository().addMatch(
|
||||
setting.getKey(), setting.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
AddressSettings defaultSetting = new AddressSettings();
|
||||
defaultSetting.setPageSizeBytes(pageSize);
|
||||
defaultSetting.setMaxSizeBytes(maxAddressSize);
|
||||
defaultSetting.setAddressFullMessagePolicy(fullPolicy);
|
||||
|
||||
server.getAddressSettingsRepository().addMatch("#", defaultSetting);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
protected Configuration createDefaultConfig(final boolean netty)
|
||||
throws Exception {
|
||||
if (netty) {
|
||||
return createDefaultConfig(new HashMap<String, Object>(),
|
||||
INVM_ACCEPTOR_FACTORY, NETTY_ACCEPTOR_FACTORY);
|
||||
} else {
|
||||
return createDefaultConfig(new HashMap<String, Object>(),
|
||||
INVM_ACCEPTOR_FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
protected Configuration createDefaultConfig(
|
||||
final Map<String, Object> params, final String... acceptors)
|
||||
throws Exception {
|
||||
ConfigurationImpl configuration = createBasicConfig(-1)
|
||||
.setJMXManagementEnabled(false)
|
||||
.clearAcceptorConfigurations();
|
||||
|
||||
for (String acceptor : acceptors) {
|
||||
TransportConfiguration transportConfig = new TransportConfiguration(
|
||||
acceptor, params);
|
||||
configuration.addAcceptorConfiguration(transportConfig);
|
||||
}
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
protected final ConfigurationImpl createBasicConfig(final int serverID) {
|
||||
ConfigurationImpl configuration = new ConfigurationImpl()
|
||||
.setSecurityEnabled(false)
|
||||
.setJournalMinFiles(2)
|
||||
.setJournalFileSize(100 * 1024)
|
||||
.setJournalType(getDefaultJournalType())
|
||||
.setJournalDirectory(getJournalDir(serverID, false))
|
||||
.setBindingsDirectory(getBindingsDir(serverID, false))
|
||||
.setPagingDirectory(getPageDir(serverID, false))
|
||||
.setLargeMessagesDirectory(getLargeMessagesDir(serverID, false))
|
||||
.setJournalCompactMinFiles(0).setJournalCompactPercentage(0)
|
||||
.setClusterPassword(CLUSTER_PASSWORD);
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
protected String getLargeMessagesDir(final int index, final boolean backup) {
|
||||
return getLargeMessagesDir(testDir, index, backup);
|
||||
}
|
||||
|
||||
protected static String getLargeMessagesDir(final String testDir,
|
||||
final int index, final boolean backup) {
|
||||
return getLargeMessagesDir(testDir)
|
||||
+ directoryNameSuffix(index, backup);
|
||||
}
|
||||
|
||||
protected String getPageDir(final int index, final boolean backup) {
|
||||
return getPageDir(testDir, index, backup);
|
||||
}
|
||||
|
||||
protected static String getPageDir(final String testDir, final int index,
|
||||
final boolean backup) {
|
||||
return getPageDir(testDir) + directoryNameSuffix(index, backup);
|
||||
}
|
||||
|
||||
protected String getBindingsDir(final int index, final boolean backup) {
|
||||
return getBindingsDir(testDir, index, backup);
|
||||
}
|
||||
|
||||
protected static String getBindingsDir(final String testDir,
|
||||
final int index, final boolean backup) {
|
||||
return getBindingsDir(testDir) + directoryNameSuffix(index, backup);
|
||||
}
|
||||
|
||||
protected String getJournalDir(final int index, final boolean backup) {
|
||||
return getJournalDir(testDir, index, backup);
|
||||
}
|
||||
|
||||
protected static String getJournalDir(final String testDir,
|
||||
final int index, final boolean backup) {
|
||||
return getJournalDir(testDir) + directoryNameSuffix(index, backup);
|
||||
}
|
||||
|
||||
private static String directoryNameSuffix(int index, boolean backup) {
|
||||
if (index == -1)
|
||||
return "";
|
||||
return index + "-" + (backup ? "B" : "L");
|
||||
}
|
||||
|
||||
protected static JournalType getDefaultJournalType() {
|
||||
if (AsynchronousFileImpl.isLoaded()) {
|
||||
return JournalType.ASYNCIO;
|
||||
} else {
|
||||
return JournalType.NIO;
|
||||
}
|
||||
}
|
||||
|
||||
protected final void clearDataRecreateServerDirs() {
|
||||
clearDataRecreateServerDirs(testDir);
|
||||
}
|
||||
|
||||
protected void clearDataRecreateServerDirs(final String testDir1) {
|
||||
// Need to delete the root
|
||||
|
||||
File file = new File(testDir1);
|
||||
deleteDirectory(file);
|
||||
file.mkdirs();
|
||||
|
||||
recreateDirectory(getJournalDir(testDir1));
|
||||
recreateDirectory(getBindingsDir(testDir1));
|
||||
recreateDirectory(getPageDir(testDir1));
|
||||
recreateDirectory(getLargeMessagesDir(testDir1));
|
||||
recreateDirectory(getClientLargeMessagesDir(testDir1));
|
||||
recreateDirectory(getTemporaryDir(testDir1));
|
||||
}
|
||||
|
||||
protected String getTemporaryDir(final String testDir1) {
|
||||
return testDir1 + "/temp";
|
||||
}
|
||||
|
||||
protected String getClientLargeMessagesDir(final String testDir1) {
|
||||
return testDir1 + "/client-large-msg";
|
||||
}
|
||||
|
||||
protected static String getLargeMessagesDir(final String testDir1) {
|
||||
return testDir1 + "/large-msg";
|
||||
}
|
||||
|
||||
protected static String getPageDir(final String testDir1) {
|
||||
return testDir1 + "/page";
|
||||
}
|
||||
|
||||
protected static String getBindingsDir(final String testDir1) {
|
||||
return testDir1 + "/bindings";
|
||||
}
|
||||
|
||||
protected static String getJournalDir(final String testDir1) {
|
||||
return testDir1 + "/journal";
|
||||
}
|
||||
|
||||
protected static final void recreateDirectory(final String directory) {
|
||||
File file = new File(directory);
|
||||
deleteDirectory(file);
|
||||
file.mkdirs();
|
||||
}
|
||||
|
||||
protected static final boolean deleteDirectory(final File directory) {
|
||||
if (directory.isDirectory()) {
|
||||
String[] files = directory.list();
|
||||
int num = 5;
|
||||
int attempts = 0;
|
||||
while (files == null && (attempts < num)) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
files = directory.list();
|
||||
attempts++;
|
||||
}
|
||||
|
||||
for (String file : files) {
|
||||
File f = new File(directory, file);
|
||||
if (!deleteDirectory(f)) {
|
||||
LOG.warn("Failed to clean up file: " + f.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return directory.delete();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
/**
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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.artemiswrapper;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.ActiveMQQueueExistsException;
|
||||
import org.apache.activemq.artemis.api.core.SimpleString;
|
||||
import org.apache.activemq.artemis.api.core.TransportConfiguration;
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.config.impl.SecurityConfiguration;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
|
||||
import org.apache.activemq.artemis.core.security.Role;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManagerImpl;
|
||||
import org.apache.activemq.artemiswrapper.ArtemisBrokerHelper;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
|
||||
public class ArtemisBrokerWrapper extends ArtemisBrokerBase
|
||||
{
|
||||
|
||||
protected Map<String, SimpleString> testQueues = new HashMap<String, SimpleString>();
|
||||
|
||||
public ArtemisBrokerWrapper(BrokerService brokerService)
|
||||
{
|
||||
this.bservice = brokerService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws Exception
|
||||
{
|
||||
testDir = temporaryFolder.getRoot().getAbsolutePath();
|
||||
clearDataRecreateServerDirs();
|
||||
server = createServer(realStore, false);
|
||||
HashMap<String, Object> params = new HashMap<String, Object>();
|
||||
params.put(TransportConstants.PORT_PROP_NAME, "61616");
|
||||
params.put(TransportConstants.PROTOCOLS_PROP_NAME, "OPENWIRE");
|
||||
TransportConfiguration transportConfiguration = new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params);
|
||||
|
||||
Configuration serverConfig = server.getConfiguration();
|
||||
|
||||
Set<TransportConfiguration> acceptors0 = serverConfig.getAcceptorConfigurations();
|
||||
Iterator<TransportConfiguration> iter0 = acceptors0.iterator();
|
||||
|
||||
while (iter0.hasNext())
|
||||
{
|
||||
System.out.println("===>: " + iter0.next());
|
||||
}
|
||||
|
||||
Map<String, AddressSettings> addressSettings = serverConfig.getAddressesSettings();
|
||||
String match = "jms.queue.#";
|
||||
AddressSettings dlaSettings = new AddressSettings();
|
||||
SimpleString dla = new SimpleString("jms.queue.ActiveMQ.DLQ");
|
||||
dlaSettings.setDeadLetterAddress(dla);
|
||||
addressSettings.put(match, dlaSettings);
|
||||
|
||||
serverConfig.getAcceptorConfigurations().add(transportConfiguration);
|
||||
if (this.bservice.enableSsl())
|
||||
{
|
||||
params = new HashMap<String, Object>();
|
||||
params.put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
|
||||
params.put(TransportConstants.PORT_PROP_NAME, 61611);
|
||||
params.put(TransportConstants.PROTOCOLS_PROP_NAME, "OPENWIRE");
|
||||
params.put(TransportConstants.KEYSTORE_PATH_PROP_NAME, bservice.SERVER_SIDE_KEYSTORE);
|
||||
params.put(TransportConstants.KEYSTORE_PASSWORD_PROP_NAME, bservice.KEYSTORE_PASSWORD);
|
||||
params.put(TransportConstants.KEYSTORE_PROVIDER_PROP_NAME, bservice.storeType);
|
||||
if (bservice.SERVER_SIDE_TRUSTSTORE != null)
|
||||
{
|
||||
params.put(TransportConstants.NEED_CLIENT_AUTH_PROP_NAME, true);
|
||||
params.put(TransportConstants.TRUSTSTORE_PATH_PROP_NAME, bservice.SERVER_SIDE_TRUSTSTORE);
|
||||
params.put(TransportConstants.TRUSTSTORE_PASSWORD_PROP_NAME, bservice.TRUSTSTORE_PASSWORD);
|
||||
params.put(TransportConstants.TRUSTSTORE_PROVIDER_PROP_NAME, bservice.storeType);
|
||||
}
|
||||
TransportConfiguration sslTransportConfig = new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params);
|
||||
serverConfig.getAcceptorConfigurations().add(sslTransportConfig);
|
||||
}
|
||||
|
||||
for (Integer port : bservice.extraConnectors)
|
||||
{
|
||||
if (port.intValue() != 61616)
|
||||
{
|
||||
//extra port
|
||||
params = new HashMap<String, Object>();
|
||||
params.put(TransportConstants.PORT_PROP_NAME, port.intValue());
|
||||
params.put(TransportConstants.PROTOCOLS_PROP_NAME, "OPENWIRE");
|
||||
TransportConfiguration extraTransportConfiguration = new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params);
|
||||
serverConfig.getAcceptorConfigurations().add(extraTransportConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
serverConfig.setSecurityEnabled(enableSecurity);
|
||||
|
||||
//extraServerConfig(serverConfig);
|
||||
|
||||
if (enableSecurity)
|
||||
{
|
||||
ActiveMQSecurityManagerImpl sm = (ActiveMQSecurityManagerImpl) server.getSecurityManager();
|
||||
SecurityConfiguration securityConfig = sm.getConfiguration();
|
||||
securityConfig.addRole("openwireSender", "sender");
|
||||
securityConfig.addUser("openwireSender", "SeNdEr");
|
||||
//sender cannot receive
|
||||
Role senderRole = new Role("sender", true, false, false, false, true, true, false);
|
||||
|
||||
securityConfig.addRole("openwireReceiver", "receiver");
|
||||
securityConfig.addUser("openwireReceiver", "ReCeIvEr");
|
||||
//receiver cannot send
|
||||
Role receiverRole = new Role("receiver", false, true, false, false, true, true, false);
|
||||
|
||||
securityConfig.addRole("openwireGuest", "guest");
|
||||
securityConfig.addUser("openwireGuest", "GuEsT");
|
||||
|
||||
//guest cannot do anything
|
||||
Role guestRole = new Role("guest", false, false, false, false, false, false, false);
|
||||
|
||||
securityConfig.addRole("openwireDestinationManager", "manager");
|
||||
securityConfig.addUser("openwireDestinationManager", "DeStInAtIoN");
|
||||
|
||||
//guest cannot do anything
|
||||
Role destRole = new Role("manager", false, false, false, false, true, true, false);
|
||||
|
||||
Map<String, Set<Role>> settings = server.getConfiguration().getSecurityRoles();
|
||||
if (settings == null)
|
||||
{
|
||||
settings = new HashMap<String, Set<Role>>();
|
||||
server.getConfiguration().setSecurityRoles(settings);
|
||||
}
|
||||
Set<Role> anySet = settings.get("#");
|
||||
if (anySet == null)
|
||||
{
|
||||
anySet = new HashSet<Role>();
|
||||
settings.put("#", anySet);
|
||||
}
|
||||
anySet.add(senderRole);
|
||||
anySet.add(receiverRole);
|
||||
anySet.add(guestRole);
|
||||
anySet.add(destRole);
|
||||
}
|
||||
/* no need to start jms server here
|
||||
jmsServer = new JMSServerManagerImpl(server);
|
||||
jmsServer.setContext(new InVMNamingContext());
|
||||
jmsServer.start();
|
||||
*/
|
||||
Set<TransportConfiguration> acceptors = serverConfig.getAcceptorConfigurations();
|
||||
Iterator<TransportConfiguration> iter = acceptors.iterator();
|
||||
|
||||
while (iter.hasNext())
|
||||
{
|
||||
System.out.println(">: " + iter.next());
|
||||
}
|
||||
server.start();
|
||||
|
||||
/*
|
||||
registerConnectionFactory();
|
||||
mbeanServer = MBeanServerFactory.createMBeanServer();
|
||||
*/
|
||||
|
||||
ArtemisBrokerHelper.setBroker(this.bservice);
|
||||
stopped = false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
testQueues.clear();
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
public void makeSureQueueExists(String qname) throws Exception
|
||||
{
|
||||
synchronized (testQueues)
|
||||
{
|
||||
SimpleString coreQ = testQueues.get(qname);
|
||||
if (coreQ == null)
|
||||
{
|
||||
coreQ = new SimpleString("jms.queue." + qname);
|
||||
try
|
||||
{
|
||||
this.server.createQueue(coreQ, coreQ, null, false, false);
|
||||
testQueues.put(qname, coreQ);
|
||||
}
|
||||
catch (ActiveMQQueueExistsException e)
|
||||
{
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* 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.artemiswrapper;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.naming.CompoundName;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.NameParser;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:ovidiu@feodorov.com">Ovidiu Feodorov</a>
|
||||
* @version <tt>$Revision: 2868 $</tt>
|
||||
*
|
||||
*/
|
||||
public class InVMNameParser implements NameParser, Serializable
|
||||
{
|
||||
// Constants -----------------------------------------------------
|
||||
|
||||
private static final long serialVersionUID = 2925203703371001031L;
|
||||
|
||||
// Static --------------------------------------------------------
|
||||
|
||||
static Properties syntax;
|
||||
|
||||
static
|
||||
{
|
||||
InVMNameParser.syntax = new Properties();
|
||||
InVMNameParser.syntax.put("jndi.syntax.direction", "left_to_right");
|
||||
InVMNameParser.syntax.put("jndi.syntax.ignorecase", "false");
|
||||
InVMNameParser.syntax.put("jndi.syntax.separator", "/");
|
||||
}
|
||||
|
||||
// Attributes ----------------------------------------------------
|
||||
|
||||
// Constructors --------------------------------------------------
|
||||
|
||||
// Public --------------------------------------------------------
|
||||
|
||||
public static Properties getSyntax()
|
||||
{
|
||||
return InVMNameParser.syntax;
|
||||
}
|
||||
|
||||
public Name parse(final String name) throws NamingException
|
||||
{
|
||||
return new CompoundName(name, InVMNameParser.syntax);
|
||||
}
|
||||
|
||||
// Package protected ---------------------------------------------
|
||||
|
||||
// Protected -----------------------------------------------------
|
||||
|
||||
// Private -------------------------------------------------------
|
||||
|
||||
// Inner classes -------------------------------------------------
|
||||
|
||||
}
|
|
@ -0,0 +1,370 @@
|
|||
/**
|
||||
* 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.artemiswrapper;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.Binding;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.NameAlreadyBoundException;
|
||||
import javax.naming.NameClassPair;
|
||||
import javax.naming.NameNotFoundException;
|
||||
import javax.naming.NameParser;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.RefAddr;
|
||||
import javax.naming.Reference;
|
||||
|
||||
public class InVMNamingContext implements Context, Serializable
|
||||
{
|
||||
// Constants -----------------------------------------------------
|
||||
|
||||
private static final long serialVersionUID = 385743957345L;
|
||||
|
||||
// Static --------------------------------------------------------
|
||||
|
||||
// Attributes ----------------------------------------------------
|
||||
|
||||
protected Map<String, Object> map;
|
||||
|
||||
protected NameParser parser = new InVMNameParser();
|
||||
|
||||
private String nameInNamespace = "";
|
||||
|
||||
// Constructors --------------------------------------------------
|
||||
|
||||
public InVMNamingContext()
|
||||
{
|
||||
map = Collections.synchronizedMap(new HashMap<String, Object>());
|
||||
}
|
||||
|
||||
public InVMNamingContext(final String nameInNamespace)
|
||||
{
|
||||
this();
|
||||
this.nameInNamespace = nameInNamespace;
|
||||
}
|
||||
|
||||
// Context implementation ----------------------------------------
|
||||
|
||||
public Object lookup(final Name name) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Object lookup(String name) throws NamingException
|
||||
{
|
||||
name = trimSlashes(name);
|
||||
int i = name.indexOf("/");
|
||||
String tok = i == -1 ? name : name.substring(0, i);
|
||||
Object value = map.get(tok);
|
||||
if (value == null)
|
||||
{
|
||||
throw new NameNotFoundException("Name not found: " + tok);
|
||||
}
|
||||
if (value instanceof InVMNamingContext && i != -1)
|
||||
{
|
||||
return ((InVMNamingContext)value).lookup(name.substring(i));
|
||||
}
|
||||
if (value instanceof Reference)
|
||||
{
|
||||
Reference ref = (Reference)value;
|
||||
RefAddr refAddr = ref.get("nns");
|
||||
|
||||
// we only deal with references create by NonSerializableFactory
|
||||
String key = (String)refAddr.getContent();
|
||||
return NonSerializableFactory.lookup(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public void bind(final Name name, final Object obj) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void bind(final String name, final Object obj) throws NamingException
|
||||
{
|
||||
internalBind(name, obj, false);
|
||||
}
|
||||
|
||||
public void rebind(final Name name, final Object obj) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void rebind(final String name, final Object obj) throws NamingException
|
||||
{
|
||||
internalBind(name, obj, true);
|
||||
}
|
||||
|
||||
public void unbind(final Name name) throws NamingException
|
||||
{
|
||||
unbind(name.toString());
|
||||
}
|
||||
|
||||
public void unbind(String name) throws NamingException
|
||||
{
|
||||
name = trimSlashes(name);
|
||||
int i = name.indexOf("/");
|
||||
boolean terminal = i == -1;
|
||||
if (terminal)
|
||||
{
|
||||
map.remove(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
String tok = name.substring(0, i);
|
||||
InVMNamingContext c = (InVMNamingContext)map.get(tok);
|
||||
if (c == null)
|
||||
{
|
||||
throw new NameNotFoundException("Context not found: " + tok);
|
||||
}
|
||||
c.unbind(name.substring(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void rename(final Name oldName, final Name newName) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void rename(final String oldName, final String newName) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public NamingEnumeration<NameClassPair> list(final Name name) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public NamingEnumeration<NameClassPair> list(final String name) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public NamingEnumeration<Binding> listBindings(final Name name) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public NamingEnumeration<Binding> listBindings(String contextName) throws NamingException
|
||||
{
|
||||
contextName = trimSlashes(contextName);
|
||||
if (!"".equals(contextName) && !".".equals(contextName))
|
||||
{
|
||||
try
|
||||
{
|
||||
return ((InVMNamingContext)lookup(contextName)).listBindings("");
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new NamingException(t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
List<Binding> l = new ArrayList<Binding>();
|
||||
for (Object element : map.keySet())
|
||||
{
|
||||
String name = (String)element;
|
||||
Object object = map.get(name);
|
||||
l.add(new Binding(name, object));
|
||||
}
|
||||
return new NamingEnumerationImpl<Binding>(l.iterator());
|
||||
}
|
||||
|
||||
public void destroySubcontext(final Name name) throws NamingException
|
||||
{
|
||||
destroySubcontext(name.toString());
|
||||
}
|
||||
|
||||
public void destroySubcontext(final String name) throws NamingException
|
||||
{
|
||||
map.remove(trimSlashes(name));
|
||||
}
|
||||
|
||||
public Context createSubcontext(final Name name) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Context createSubcontext(String name) throws NamingException
|
||||
{
|
||||
name = trimSlashes(name);
|
||||
if (map.get(name) != null)
|
||||
{
|
||||
throw new NameAlreadyBoundException(name);
|
||||
}
|
||||
InVMNamingContext c = new InVMNamingContext(getNameInNamespace());
|
||||
map.put(name, c);
|
||||
return c;
|
||||
}
|
||||
|
||||
public Object lookupLink(final Name name) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Object lookupLink(final String name) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public NameParser getNameParser(final Name name) throws NamingException
|
||||
{
|
||||
return getNameParser(name.toString());
|
||||
}
|
||||
|
||||
public NameParser getNameParser(final String name) throws NamingException
|
||||
{
|
||||
return parser;
|
||||
}
|
||||
|
||||
public Name composeName(final Name name, final Name prefix) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String composeName(final String name, final String prefix) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Object addToEnvironment(final String propName, final Object propVal) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Object removeFromEnvironment(final String propName) throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Hashtable<String, String> getEnvironment() throws NamingException
|
||||
{
|
||||
Hashtable<String, String> env = new Hashtable<String, String>();
|
||||
env.put("java.naming.factory.initial", "org.apache.activemq.artemis.jms.tests.tools.container.InVMInitialContextFactory");
|
||||
return env;
|
||||
}
|
||||
|
||||
public void close() throws NamingException
|
||||
{
|
||||
}
|
||||
|
||||
public String getNameInNamespace() throws NamingException
|
||||
{
|
||||
return nameInNamespace;
|
||||
}
|
||||
|
||||
// Public --------------------------------------------------------
|
||||
|
||||
// Package protected ---------------------------------------------
|
||||
|
||||
// Protected -----------------------------------------------------
|
||||
|
||||
// Private -------------------------------------------------------
|
||||
|
||||
private String trimSlashes(String s)
|
||||
{
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
if (i == s.length() || s.charAt(i) != '/')
|
||||
{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
s = s.substring(i);
|
||||
i = s.length() - 1;
|
||||
while (true)
|
||||
{
|
||||
if (i == -1 || s.charAt(i) != '/')
|
||||
{
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
return s.substring(0, i + 1);
|
||||
}
|
||||
|
||||
private void internalBind(String name, final Object obj, final boolean rebind) throws NamingException
|
||||
{
|
||||
name = trimSlashes(name);
|
||||
int i = name.lastIndexOf("/");
|
||||
InVMNamingContext c = this;
|
||||
if (i != -1)
|
||||
{
|
||||
String path = name.substring(0, i);
|
||||
c = (InVMNamingContext)lookup(path);
|
||||
}
|
||||
name = name.substring(i + 1);
|
||||
if (!rebind && c.map.get(name) != null)
|
||||
{
|
||||
throw new NameAlreadyBoundException(name);
|
||||
}
|
||||
c.map.put(name, obj);
|
||||
}
|
||||
|
||||
// Inner classes -------------------------------------------------
|
||||
|
||||
private class NamingEnumerationImpl<T> implements NamingEnumeration<T>
|
||||
{
|
||||
private final Iterator<T> iterator;
|
||||
|
||||
NamingEnumerationImpl(final Iterator<T> bindingIterator)
|
||||
{
|
||||
iterator = bindingIterator;
|
||||
}
|
||||
|
||||
public void close() throws NamingException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean hasMore() throws NamingException
|
||||
{
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
public T next() throws NamingException
|
||||
{
|
||||
return iterator.next();
|
||||
}
|
||||
|
||||
public boolean hasMoreElements()
|
||||
{
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
public T nextElement()
|
||||
{
|
||||
return iterator.next();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* 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.artemiswrapper;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.RefAddr;
|
||||
import javax.naming.Reference;
|
||||
import javax.naming.StringRefAddr;
|
||||
import javax.naming.spi.ObjectFactory;
|
||||
|
||||
//import org.jboss.util.naming.Util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* used by the default context when running in embedded local configuration
|
||||
*
|
||||
* @author <a href="ataylor@redhat.com">Andy Taylor</a>
|
||||
*/
|
||||
public class NonSerializableFactory implements ObjectFactory
|
||||
{
|
||||
|
||||
public NonSerializableFactory()
|
||||
{
|
||||
}
|
||||
/*
|
||||
public static void unbind(final Context ctx, final String strName) throws NamingException
|
||||
{
|
||||
Name name = ctx.getNameParser("").parse(strName);
|
||||
int size = name.size();
|
||||
String atom = name.get(size - 1);
|
||||
Context parentCtx = Util.createSubcontext(ctx, name.getPrefix(size - 1));
|
||||
String key = new StringBuilder().append(parentCtx.getNameInNamespace()).append("/").append(atom).toString();
|
||||
NonSerializableFactory.getWrapperMap().remove(key);
|
||||
Util.unbind(ctx, strName);
|
||||
}
|
||||
|
||||
public static void rebind(final Context ctx, final String strName, final Object value) throws NamingException
|
||||
{
|
||||
Name name = ctx.getNameParser("").parse(strName);
|
||||
int size = name.size();
|
||||
String atom = name.get(size - 1);
|
||||
Context parentCtx = Util.createSubcontext(ctx, name.getPrefix(size - 1));
|
||||
String key = new StringBuilder().append(parentCtx.getNameInNamespace()).append("/").append(atom).toString();
|
||||
NonSerializableFactory.getWrapperMap().put(key, value);
|
||||
String className = value.getClass().getName();
|
||||
String factory = NonSerializableFactory.class.getName();
|
||||
StringRefAddr addr = new StringRefAddr("nns", key);
|
||||
Reference memoryRef = new Reference(className, addr, factory, null);
|
||||
parentCtx.rebind(atom, memoryRef);
|
||||
}
|
||||
|
||||
public static void bind(final Context ctx, final String strName, final Object value) throws NamingException
|
||||
{
|
||||
Name name = ctx.getNameParser("").parse(strName);
|
||||
int size = name.size();
|
||||
String atom = name.get(size - 1);
|
||||
Context parentCtx = Util.createSubcontext(ctx, name.getPrefix(size - 1));
|
||||
String key = new StringBuilder().append(parentCtx.getNameInNamespace()).append("/").append(atom).toString();
|
||||
NonSerializableFactory.getWrapperMap().put(key, value);
|
||||
String className = value.getClass().getName();
|
||||
String factory = NonSerializableFactory.class.getName();
|
||||
StringRefAddr addr = new StringRefAddr("nns", key);
|
||||
Reference memoryRef = new Reference(className, addr, factory, null);
|
||||
|
||||
parentCtx.bind(atom, memoryRef);
|
||||
}
|
||||
*/
|
||||
public static Object lookup(final String name) throws NamingException
|
||||
{
|
||||
if (NonSerializableFactory.getWrapperMap().get(name) == null)
|
||||
{
|
||||
throw new NamingException(name + " not found");
|
||||
}
|
||||
return NonSerializableFactory.getWrapperMap().get(name);
|
||||
}
|
||||
|
||||
public Object getObjectInstance(final Object obj, final Name name, final Context nameCtx, final Hashtable<?, ?> env) throws Exception
|
||||
{
|
||||
Reference ref = (Reference) obj;
|
||||
RefAddr addr = ref.get("nns");
|
||||
String key = (String) addr.getContent();
|
||||
return NonSerializableFactory.getWrapperMap().get(key);
|
||||
}
|
||||
|
||||
public static Map<String, Object> getWrapperMap()
|
||||
{
|
||||
return NonSerializableFactory.wrapperMap;
|
||||
}
|
||||
|
||||
private static Map<String, Object> wrapperMap = Collections.synchronizedMap(new HashMap<String, Object>());
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
org.apache.activemq.artemis.core.protocol.openwire.OpenWireProtocolManagerFactory
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
## ---------------------------------------------------------------------------
|
||||
## 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.
|
||||
## ---------------------------------------------------------------------------
|
||||
|
||||
# Remote addresses for the other brokers in mesh
|
||||
|
||||
|
||||
# 1a
|
||||
1a.name=1a-nc
|
||||
1a.uri=failover:(tcp://localhost:6106)?randomize=false
|
||||
1a.transport=tcp://localhost:6106
|
||||
1a.jmx=1090
|
||||
1a.data=target/data/1a_store
|
||||
|
||||
# 1b
|
||||
1b.name=1b-nc
|
||||
1b.uri=failover:(tcp://localhost:6107)?randomize=false
|
||||
1b.transport=tcp://localhost:6107
|
||||
1b.jmx=1091
|
||||
1b.data=target/data/1b_store
|
||||
|
||||
# 2a
|
||||
2a.name=2a-nc
|
||||
2a.uri=failover:(tcp://localhost:6108)?randomize=false
|
||||
2a.transport=tcp://localhost:6108
|
||||
2a.jmx=1092
|
||||
2a.data=target/data/2a_store
|
||||
|
||||
# 2b
|
||||
2b.name=2b-nc
|
||||
2b.uri=failover:(tcp://localhost:6109)?randomize=false
|
||||
2b.transport=tcp://localhost:6109
|
||||
2b.jmx=1093
|
||||
2b.data=target/data/2b_store
|
||||
|
||||
# 3a
|
||||
3a.name=3a-nc
|
||||
3a.uri=failover:(tcp://localhost:6110)?randomize=false
|
||||
3a.transport=tcp://localhost:6110
|
||||
3a.jmx=1094
|
||||
3a.data=target/data/3a_store
|
||||
|
||||
# 3b
|
||||
3b.name=3b-nc
|
||||
3b.uri=failover:(tcp://localhost:6111)?randomize=false
|
||||
3b.transport=tcp://localhost:6111
|
||||
3b.jmx=1095
|
||||
3b.data=target/data/3b_store
|
|
@ -0,0 +1,58 @@
|
|||
<?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 -->
|
|
@ -0,0 +1,37 @@
|
|||
<?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 -->
|
|
@ -0,0 +1,24 @@
|
|||
## ---------------------------------------------------------------------------
|
||||
## 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.
|
||||
## ---------------------------------------------------------------------------
|
||||
|
||||
# Defines credentials that will be used by components (like web console) to access the broker
|
||||
|
||||
activemq.username=system
|
||||
#activemq.password=manager
|
||||
activemq.password=ENC(mYRkg+4Q4hua1kvpCCI2hg==)
|
||||
#guest.password=password
|
||||
guest.password=ENC(Cf3Jf3tM+UrSOoaKU50od5CuBa8rxjoL)
|
|
@ -0,0 +1,18 @@
|
|||
## ---------------------------------------------------------------------------
|
||||
## 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.
|
||||
## ---------------------------------------------------------------------------
|
||||
|
||||
admin readwrite
|
|
@ -0,0 +1,18 @@
|
|||
## ---------------------------------------------------------------------------
|
||||
## 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.
|
||||
## ---------------------------------------------------------------------------
|
||||
|
||||
admin activemq
|
|
@ -0,0 +1,38 @@
|
|||
## ---------------------------------------------------------------------------
|
||||
## 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: jndi
|
||||
|
||||
java.naming.factory.initial = org.apache.activemq.jndi.ActiveMQInitialContextFactory
|
||||
|
||||
# use the following property to configure the default connector
|
||||
java.naming.provider.url = vm://localhost
|
||||
|
||||
# use the following property to specify the JNDI name the connection factory
|
||||
# should appear as.
|
||||
#connectionFactoryNames = connectionFactory, queueConnectionFactory, topicConnectionFactry
|
||||
|
||||
# register some queues in JNDI using the form
|
||||
# queue.[jndiName] = [physicalName]
|
||||
queue.MyQueue = example.MyQueue
|
||||
|
||||
|
||||
# register some topics in JNDI using the form
|
||||
# topic.[jndiName] = [physicalName]
|
||||
topic.MyTopic = example.MyTopic
|
||||
|
||||
# END SNIPPET: jndi
|
|
@ -0,0 +1,46 @@
|
|||
## ---------------------------------------------------------------------------
|
||||
## 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.
|
||||
## ---------------------------------------------------------------------------
|
||||
|
||||
#
|
||||
# The logging properties used during tests..
|
||||
#
|
||||
log4j.rootLogger=INFO, out, stdout
|
||||
|
||||
#log4j.logger.org.apache.activemq.broker.scheduler=DEBUG
|
||||
#log4j.logger.org.apache.activemq.store.kahadb.scheduler=DEBUG
|
||||
#log4j.logger.org.apache.activemq.network.DemandForwardingBridgeSupport=DEBUG
|
||||
#log4j.logger.org.apache.activemq.transport.failover=TRACE
|
||||
#log4j.logger.org.apache.activemq.store.jdbc=TRACE
|
||||
#log4j.logger.org.apache.activemq.store.kahadb=TRACE
|
||||
#log4j.logger.org.apache.activemq.broker.region.cursors.AbstractStoreCursor=DEBUG
|
||||
#log4j.logger.org.apache.activemq.store.jdbc.JDBCMessageStore=DEBUG
|
||||
#log4j.logger.org.apache.activemq.store.kahadb.disk.journal=DEBUG
|
||||
#log4j.logger.org.apache.activemq.store.kahadb.AbstractKahaDBStore=DEBUG
|
||||
|
||||
# CONSOLE appender not used by default
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] - %-5p %-30.30c{1} - %m%n
|
||||
#log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] - %-5p %-30.30c{1} - %-10.10X{activemq.broker} %-20.20X{activemq.connector} %-10.10X{activemq.destination} - %m%n
|
||||
|
||||
# File appender
|
||||
log4j.appender.out=org.apache.log4j.FileAppender
|
||||
log4j.appender.out.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] - %-5p %-30.30c{1} - %m%n
|
||||
#log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] - %-5p %-30.30c{1} - %-10.10X{activemq.broker} %-20.20X{activemq.connector} %-10.10X{activemq.destination} - %m%n
|
||||
log4j.appender.out.file=target/activemq-test.log
|
||||
log4j.appender.out.append=true
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
activemq-domain {
|
||||
org.apache.activemq.jaas.PropertiesLoginModule required
|
||||
debug=true
|
||||
org.apache.activemq.jaas.properties.user="org/apache/activemq/security/users.properties"
|
||||
org.apache.activemq.jaas.properties.group="org/apache/activemq/security/groups.properties";
|
||||
};
|
||||
|
||||
activemq-guest-domain {
|
||||
org.apache.activemq.jaas.PropertiesLoginModule sufficient
|
||||
debug=true
|
||||
org.apache.activemq.jaas.properties.user="org/apache/activemq/security/users.properties"
|
||||
org.apache.activemq.jaas.properties.group="org/apache/activemq/security/groups.properties";
|
||||
org.apache.activemq.jaas.GuestLoginModule sufficient
|
||||
debug=true
|
||||
org.apache.activemq.jaas.guest.user="guest"
|
||||
org.apache.activemq.jaas.guest.group="guests";
|
||||
};
|
||||
|
||||
activemq-guest-when-no-creds-only-domain {
|
||||
org.apache.activemq.jaas.GuestLoginModule sufficient
|
||||
debug=true
|
||||
credentialsInvalidate=true
|
||||
org.apache.activemq.jaas.guest.user="guest"
|
||||
org.apache.activemq.jaas.guest.group="guests";
|
||||
|
||||
org.apache.activemq.jaas.PropertiesLoginModule requisite
|
||||
debug=true
|
||||
org.apache.activemq.jaas.properties.user="org/apache/activemq/security/users.properties"
|
||||
org.apache.activemq.jaas.properties.group="org/apache/activemq/security/groups.properties";
|
||||
};
|
||||
|
||||
cert-login {
|
||||
org.apache.activemq.jaas.TextFileCertificateLoginModule required
|
||||
debug=true
|
||||
org.apache.activemq.jaas.textfiledn.user="org/apache/activemq/security/users.properties"
|
||||
org.apache.activemq.jaas.textfiledn.group="org/apache/activemq/security/groups.properties";
|
||||
|
||||
};
|
||||
|
||||
broker1 {
|
||||
org.apache.activemq.jaas.TextFileCertificateLoginModule required
|
||||
debug=true
|
||||
org.apache.activemq.jaas.textfiledn.user="org/apache/activemq/security/users1.properties"
|
||||
org.apache.activemq.jaas.textfiledn.group="org/apache/activemq/security/groups.properties";
|
||||
};
|
||||
|
||||
broker2 {
|
||||
org.apache.activemq.jaas.TextFileCertificateLoginModule required
|
||||
debug=true
|
||||
org.apache.activemq.jaas.textfiledn.user="org/apache/activemq/security/users2.properties"
|
||||
org.apache.activemq.jaas.textfiledn.group="org/apache/activemq/security/groups.properties";
|
||||
};
|
||||
|
||||
LDAPLogin {
|
||||
org.apache.activemq.jaas.LDAPLoginModule required
|
||||
debug=true
|
||||
initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
|
||||
connectionURL="ldap://localhost:1024"
|
||||
connectionUsername="uid=admin,ou=system"
|
||||
connectionPassword=secret
|
||||
connectionProtocol=s
|
||||
authentication=simple
|
||||
userBase="ou=User,ou=ActiveMQ,ou=system"
|
||||
userSearchMatching="(uid={0})"
|
||||
userSearchSubtree=false
|
||||
roleBase="ou=Group,ou=ActiveMQ,ou=system"
|
||||
roleName=cn
|
||||
roleSearchMatching="(uid={1})"
|
||||
roleSearchSubtree=true
|
||||
;
|
||||
};
|
|
@ -0,0 +1,261 @@
|
|||
/**
|
||||
* 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.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import javax.jms.ExceptionListener;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.apache.activemq.broker.BrokerRegistry;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.TransportConnector;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ActiveMQConnectionFactoryTest extends CombinationTestSupport {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ActiveMQConnectionFactoryTest.class);
|
||||
|
||||
private ActiveMQConnection connection;
|
||||
private BrokerService broker;
|
||||
|
||||
public void testUseURIToSetUseClientIDPrefixOnConnectionFactory() throws URISyntaxException, JMSException {
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(
|
||||
"vm://localhost?jms.clientIDPrefix=Cheese");
|
||||
assertEquals("Cheese", cf.getClientIDPrefix());
|
||||
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
connection.start();
|
||||
|
||||
String clientID = connection.getClientID();
|
||||
LOG.info("Got client ID: " + clientID);
|
||||
|
||||
assertTrue("should start with Cheese! but was: " + clientID, clientID.startsWith("Cheese"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
// Try our best to close any previously opend connection.
|
||||
try {
|
||||
connection.close();
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
// Try our best to stop any previously started broker.
|
||||
try {
|
||||
broker.stop();
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testUseURIToSetOptionsOnConnectionFactory() throws URISyntaxException, JMSException {
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("vm://localhost?jms.useAsyncSend=true");
|
||||
assertTrue(cf.isUseAsyncSend());
|
||||
// the broker url have been adjusted.
|
||||
assertEquals("vm://localhost", cf.getBrokerURL());
|
||||
|
||||
cf = new ActiveMQConnectionFactory("vm://localhost?jms.useAsyncSend=false");
|
||||
assertFalse(cf.isUseAsyncSend());
|
||||
// the broker url have been adjusted.
|
||||
assertEquals("vm://localhost", cf.getBrokerURL());
|
||||
|
||||
cf = new ActiveMQConnectionFactory("vm:(broker:()/localhost)?jms.useAsyncSend=true");
|
||||
assertTrue(cf.isUseAsyncSend());
|
||||
// the broker url have been adjusted.
|
||||
assertEquals("vm:(broker:()/localhost)", cf.getBrokerURL());
|
||||
|
||||
cf = new ActiveMQConnectionFactory("vm://localhost?jms.auditDepth=5000");
|
||||
assertEquals(5000, cf.getAuditDepth());
|
||||
}
|
||||
|
||||
public void testUseURIToConfigureRedeliveryPolicy() throws URISyntaxException, JMSException {
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(
|
||||
"vm://localhost?jms.redeliveryPolicy.maximumRedeliveries=2");
|
||||
assertEquals("connection redeliveries", 2, cf.getRedeliveryPolicy().getMaximumRedeliveries());
|
||||
|
||||
ActiveMQConnection connection = (ActiveMQConnection)cf.createConnection();
|
||||
assertEquals("connection redeliveries", 2, connection.getRedeliveryPolicy().getMaximumRedeliveries());
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
ActiveMQMessageConsumer consumer = (ActiveMQMessageConsumer)session.createConsumer(session
|
||||
.createQueue("FOO.BAR"));
|
||||
assertEquals("consumer redeliveries", 2, consumer.getRedeliveryPolicy().getMaximumRedeliveries());
|
||||
connection.close();
|
||||
}
|
||||
|
||||
public void testCreateVMConnectionWithEmbdeddBroker() throws URISyntaxException, JMSException {
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("vm://myBroker2?broker.persistent=false");
|
||||
// Make sure the broker is not created until the connection is
|
||||
// instantiated.
|
||||
assertNull(BrokerRegistry.getInstance().lookup("myBroker2"));
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
// This should create the connection.
|
||||
assertNotNull(connection);
|
||||
// Verify the broker was created.
|
||||
assertNotNull(BrokerRegistry.getInstance().lookup("myBroker2"));
|
||||
|
||||
connection.close();
|
||||
|
||||
// Verify the broker was destroyed.
|
||||
assertNull(BrokerRegistry.getInstance().lookup("myBroker2"));
|
||||
}
|
||||
|
||||
public void testGetBrokerName() throws URISyntaxException, JMSException {
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
connection.start();
|
||||
|
||||
String brokerName = connection.getBrokerName();
|
||||
LOG.info("Got broker name: " + brokerName);
|
||||
|
||||
assertNotNull("No broker name available!", brokerName);
|
||||
}
|
||||
|
||||
public void testCreateTcpConnectionUsingAllocatedPort() throws Exception {
|
||||
assertCreateConnection("tcp://localhost:0?wireFormat.tcpNoDelayEnabled=true");
|
||||
}
|
||||
|
||||
public void testCreateTcpConnectionUsingKnownPort() throws Exception {
|
||||
assertCreateConnection("tcp://localhost:61610?wireFormat.tcpNoDelayEnabled=true");
|
||||
}
|
||||
|
||||
public void testCreateTcpConnectionUsingKnownLocalPort() throws Exception {
|
||||
broker = new BrokerService();
|
||||
broker.setPersistent(false);
|
||||
broker.addConnector("tcp://localhost:61610?wireFormat.tcpNoDelayEnabled=true");
|
||||
broker.start();
|
||||
|
||||
// This should create the connection.
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61610/localhost:51610");
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
assertNotNull(connection);
|
||||
|
||||
connection.close();
|
||||
|
||||
broker.stop();
|
||||
}
|
||||
|
||||
public void testConnectionFailsToConnectToVMBrokerThatIsNotRunning() throws Exception {
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost?create=false");
|
||||
try {
|
||||
factory.createConnection();
|
||||
fail("Expected connection failure.");
|
||||
} catch (JMSException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testFactorySerializable() throws Exception {
|
||||
String clientID = "TestClientID";
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory();
|
||||
cf.setClientID(clientID);
|
||||
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
|
||||
ObjectOutputStream objectsOut = new ObjectOutputStream(bytesOut);
|
||||
objectsOut.writeObject(cf);
|
||||
objectsOut.flush();
|
||||
byte[] data = bytesOut.toByteArray();
|
||||
ByteArrayInputStream bytesIn = new ByteArrayInputStream(data);
|
||||
ObjectInputStream objectsIn = new ObjectInputStream(bytesIn);
|
||||
cf = (ActiveMQConnectionFactory)objectsIn.readObject();
|
||||
assertEquals(cf.getClientID(), clientID);
|
||||
}
|
||||
|
||||
public void testSetExceptionListener() throws Exception {
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
assertNull(connection.getExceptionListener());
|
||||
|
||||
ExceptionListener exListener = new ExceptionListener() {
|
||||
@Override
|
||||
public void onException(JMSException arg0) {
|
||||
}
|
||||
};
|
||||
cf.setExceptionListener(exListener);
|
||||
connection.close();
|
||||
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
assertNotNull(connection.getExceptionListener());
|
||||
assertEquals(exListener, connection.getExceptionListener());
|
||||
connection.close();
|
||||
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
assertEquals(exListener, connection.getExceptionListener());
|
||||
|
||||
assertEquals(exListener, cf.getExceptionListener());
|
||||
connection.close();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void testSetClientInternalExceptionListener() throws Exception {
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
assertNull(connection.getClientInternalExceptionListener());
|
||||
|
||||
ClientInternalExceptionListener listener = new ClientInternalExceptionListener() {
|
||||
@Override
|
||||
public void onException(Throwable exception) {
|
||||
}
|
||||
};
|
||||
connection.setClientInternalExceptionListener(listener);
|
||||
cf.setClientInternalExceptionListener(listener);
|
||||
connection.close();
|
||||
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
assertNotNull(connection.getClientInternalExceptionListener());
|
||||
assertEquals(listener, connection.getClientInternalExceptionListener());
|
||||
connection.close();
|
||||
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
assertEquals(listener, connection.getClientInternalExceptionListener());
|
||||
assertEquals(listener, cf.getClientInternalExceptionListener());
|
||||
connection.close();
|
||||
|
||||
}
|
||||
|
||||
protected void assertCreateConnection(String uri) throws Exception {
|
||||
// Start up a broker with a tcp connector.
|
||||
broker = new BrokerService();
|
||||
broker.setPersistent(false);
|
||||
broker.setUseJmx(false);
|
||||
TransportConnector connector = broker.addConnector(uri);
|
||||
broker.start();
|
||||
|
||||
URI temp = new URI(uri);
|
||||
// URI connectURI = connector.getServer().getConnectURI();
|
||||
// TODO this sometimes fails when using the actual local host name
|
||||
URI currentURI = new URI(connector.getPublishableConnectString());
|
||||
|
||||
// sometimes the actual host name doesn't work in this test case
|
||||
// e.g. on OS X so lets use the original details but just use the actual
|
||||
// port
|
||||
URI connectURI = new URI(temp.getScheme(), temp.getUserInfo(), temp.getHost(), currentURI.getPort(),
|
||||
temp.getPath(), temp.getQuery(), temp.getFragment());
|
||||
|
||||
LOG.info("connection URI is: " + connectURI);
|
||||
|
||||
// This should create the connection.
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(connectURI);
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
assertNotNull(connection);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* 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.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Deprecated
|
||||
public class ActiveMQInputStreamTest extends TestCase {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ActiveMQInputStreamTest.class);
|
||||
|
||||
private static final String BROKER_URL = "tcp://localhost:0";
|
||||
private static final String DESTINATION = "destination";
|
||||
private static final int STREAM_LENGTH = 64 * 1024 + 0; // change 0 to 1 to make it not crash
|
||||
|
||||
private BrokerService broker;
|
||||
private String connectionUri;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
broker = new BrokerService();
|
||||
broker.setUseJmx(false);
|
||||
broker.setPersistent(false);
|
||||
broker.setDestinations(new ActiveMQDestination[] {
|
||||
ActiveMQDestination.createDestination(DESTINATION, ActiveMQDestination.QUEUE_TYPE),
|
||||
});
|
||||
broker.addConnector(BROKER_URL);
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
|
||||
connectionUri = broker.getTransportConnectors().get(0).getPublishableConnectString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
}
|
||||
|
||||
public void testInputStreamSetSyncSendOption() throws Exception {
|
||||
|
||||
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(connectionUri);
|
||||
ActiveMQConnection connection = (ActiveMQConnection) connectionFactory.createConnection();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue destination = session.createQueue(DESTINATION + "?producer.alwaysSyncSend=true");
|
||||
|
||||
OutputStream out = null;
|
||||
try {
|
||||
out = connection.createOutputStream(destination);
|
||||
|
||||
assertTrue(((ActiveMQOutputStream)out).isAlwaysSyncSend());
|
||||
|
||||
LOG.debug("writing...");
|
||||
for (int i = 0; i < STREAM_LENGTH; ++i) {
|
||||
out.write(0);
|
||||
}
|
||||
LOG.debug("wrote " + STREAM_LENGTH + " bytes");
|
||||
} finally {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = connection.createInputStream(destination);
|
||||
LOG.debug("reading...");
|
||||
int count = 0;
|
||||
while (-1 != in.read()) {
|
||||
++count;
|
||||
}
|
||||
LOG.debug("read " + count + " bytes");
|
||||
} finally {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
connection.close();
|
||||
}
|
||||
|
||||
public void testInputStreamMatchesDefaultChuckSize() throws Exception {
|
||||
|
||||
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(connectionUri);
|
||||
ActiveMQConnection connection = (ActiveMQConnection) connectionFactory.createConnection();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue destination = session.createQueue(DESTINATION);
|
||||
|
||||
OutputStream out = null;
|
||||
try {
|
||||
out = connection.createOutputStream(destination);
|
||||
LOG.debug("writing...");
|
||||
for (int i = 0; i < STREAM_LENGTH; ++i) {
|
||||
out.write(0);
|
||||
}
|
||||
LOG.debug("wrote " + STREAM_LENGTH + " bytes");
|
||||
} finally {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = connection.createInputStream(destination);
|
||||
LOG.debug("reading...");
|
||||
int count = 0;
|
||||
while (-1 != in.read()) {
|
||||
++count;
|
||||
}
|
||||
LOG.debug("read " + count + " bytes");
|
||||
} finally {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
connection.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/**
|
||||
* 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.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.activemq.broker.region.MessageReference;
|
||||
import org.apache.activemq.command.ActiveMQMessage;
|
||||
import org.apache.activemq.command.MessageId;
|
||||
import org.apache.activemq.command.ProducerId;
|
||||
import org.apache.activemq.util.IdGenerator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* ActiveMQMessageAuditTest
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ActiveMQMessageAuditTest extends TestCase {
|
||||
|
||||
static final Logger LOG = LoggerFactory.getLogger(ActiveMQMessageAuditTest.class);
|
||||
|
||||
/**
|
||||
* Constructor for ActiveMQMessageAuditTest.
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public ActiveMQMessageAuditTest(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* test case for isDuplicate
|
||||
*/
|
||||
public void testIsDuplicateString() {
|
||||
int count = 10000;
|
||||
ActiveMQMessageAudit audit = new ActiveMQMessageAudit();
|
||||
IdGenerator idGen = new IdGenerator();
|
||||
// add to a list
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
String id = idGen.generateId();
|
||||
list.add(id);
|
||||
assertFalse(audit.isDuplicate(id));
|
||||
}
|
||||
List<String> windowList = list.subList(list.size() -1 -audit.getAuditDepth(), list.size() -1);
|
||||
for (String id : windowList) {
|
||||
assertTrue("duplicate, id:" + id, audit.isDuplicate(id));
|
||||
}
|
||||
}
|
||||
|
||||
public void testIsDuplicateMessageReference() {
|
||||
int count = 10000;
|
||||
ActiveMQMessageAudit audit = new ActiveMQMessageAudit();
|
||||
// add to a list
|
||||
List<MessageReference> list = new ArrayList<MessageReference>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
ProducerId pid = new ProducerId();
|
||||
pid.setConnectionId("test");
|
||||
pid.setSessionId(0);
|
||||
pid.setValue(1);
|
||||
MessageId id = new MessageId();
|
||||
id.setProducerId(pid);
|
||||
id.setProducerSequenceId(i);
|
||||
ActiveMQMessage msg = new ActiveMQMessage();
|
||||
msg.setMessageId(id);
|
||||
list.add(msg);
|
||||
assertFalse(audit.isDuplicate(msg.getMessageId()));
|
||||
}
|
||||
List<MessageReference> windowList = list.subList(list.size() -1 -audit.getAuditDepth(), list.size() -1);
|
||||
for (MessageReference msg : windowList) {
|
||||
assertTrue("duplicate msg:" + msg, audit.isDuplicate(msg));
|
||||
}
|
||||
}
|
||||
|
||||
public void testIsInOrderString() {
|
||||
int count = 10000;
|
||||
ActiveMQMessageAudit audit = new ActiveMQMessageAudit();
|
||||
IdGenerator idGen = new IdGenerator();
|
||||
// add to a list
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
String id = idGen.generateId();
|
||||
if (i==0) {
|
||||
assertFalse(audit.isDuplicate(id));
|
||||
assertTrue(audit.isInOrder(id));
|
||||
}
|
||||
if (i > 1 && i%2 != 0) {
|
||||
list.add(id);
|
||||
}
|
||||
|
||||
}
|
||||
for (String id : list) {
|
||||
assertFalse(audit.isInOrder(id));
|
||||
assertFalse(audit.isDuplicate(id));
|
||||
}
|
||||
}
|
||||
|
||||
public void testSerialization() throws Exception {
|
||||
ActiveMQMessageAuditNoSync audit = new ActiveMQMessageAuditNoSync();
|
||||
|
||||
byte[] bytes = serialize(audit);
|
||||
LOG.debug("Length: " + bytes.length);
|
||||
audit = recover(bytes);
|
||||
|
||||
List<MessageReference> list = new ArrayList<MessageReference>();
|
||||
|
||||
for (int j = 0; j < 1000; j++) {
|
||||
ProducerId pid = new ProducerId();
|
||||
pid.setConnectionId("test");
|
||||
pid.setSessionId(0);
|
||||
pid.setValue(j);
|
||||
LOG.debug("producer " + j);
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
MessageId id = new MessageId();
|
||||
id.setProducerId(pid);
|
||||
id.setProducerSequenceId(i);
|
||||
ActiveMQMessage msg = new ActiveMQMessage();
|
||||
msg.setMessageId(id);
|
||||
list.add(msg);
|
||||
assertFalse(audit.isDuplicate(msg.getMessageId().toString()));
|
||||
|
||||
if (i % 100 == 0) {
|
||||
bytes = serialize(audit);
|
||||
LOG.debug("Length: " + bytes.length);
|
||||
audit = recover(bytes);
|
||||
}
|
||||
|
||||
if (i % 250 == 0) {
|
||||
for (MessageReference message : list) {
|
||||
audit.rollback(message.getMessageId().toString());
|
||||
}
|
||||
list.clear();
|
||||
bytes = serialize(audit);
|
||||
LOG.debug("Length: " + bytes.length);
|
||||
audit = recover(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected byte[] serialize(ActiveMQMessageAuditNoSync audit) throws Exception {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oout = new ObjectOutputStream(baos);
|
||||
oout.writeObject(audit);
|
||||
oout.flush();
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
protected ActiveMQMessageAuditNoSync recover(byte[] bytes) throws Exception {
|
||||
ObjectInputStream objectIn = new ObjectInputStream(new ByteArrayInputStream(bytes));
|
||||
return (ActiveMQMessageAuditNoSync)objectIn.readObject();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,262 @@
|
|||
/**
|
||||
* 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.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.SslBrokerService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
public class ActiveMQSslConnectionFactoryTest extends CombinationTestSupport {
|
||||
private static final Log LOG = LogFactory.getLog(ActiveMQSslConnectionFactoryTest.class);
|
||||
|
||||
public static final String KEYSTORE_TYPE = "jks";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String SERVER_KEYSTORE = "src/test/resources/server.keystore";
|
||||
public static final String TRUST_KEYSTORE = "src/test/resources/client.keystore";
|
||||
|
||||
private ActiveMQConnection connection;
|
||||
private BrokerService broker;
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
// Try our best to close any previously opend connection.
|
||||
try {
|
||||
connection.close();
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
// Try our best to stop any previously started broker.
|
||||
try {
|
||||
broker.stop();
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCreateTcpConnectionUsingKnownPort() throws Exception {
|
||||
// Control case: check that the factory can create an ordinary (non-ssl) connection.
|
||||
broker = createBroker("tcp://localhost:61610?wireFormat.tcpNoDelayEnabled=true");
|
||||
|
||||
// This should create the connection.
|
||||
ActiveMQSslConnectionFactory cf = new ActiveMQSslConnectionFactory("tcp://localhost:61610?wireFormat.tcpNoDelayEnabled=true");
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
assertNotNull(connection);
|
||||
connection.start();
|
||||
connection.stop();
|
||||
brokerStop();
|
||||
}
|
||||
|
||||
public void testCreateFailoverTcpConnectionUsingKnownPort() throws Exception {
|
||||
// Control case: check that the factory can create an ordinary (non-ssl) connection.
|
||||
broker = createBroker("tcp://localhost:61610?wireFormat.tcpNoDelayEnabled=true");
|
||||
|
||||
// This should create the connection.
|
||||
ActiveMQSslConnectionFactory cf = new ActiveMQSslConnectionFactory("failover:(tcp://localhost:61610?wireFormat.tcpNoDelayEnabled=true)");
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
assertNotNull(connection);
|
||||
connection.start();
|
||||
connection.stop();
|
||||
brokerStop();
|
||||
}
|
||||
|
||||
public void testCreateSslConnection() throws Exception {
|
||||
// Create SSL/TLS connection with trusted cert from truststore.
|
||||
String sslUri = "ssl://localhost:61611";
|
||||
broker = createSslBroker(sslUri);
|
||||
assertNotNull(broker);
|
||||
|
||||
// This should create the connection.
|
||||
ActiveMQSslConnectionFactory cf = new ActiveMQSslConnectionFactory(sslUri);
|
||||
cf.setTrustStore("server.keystore");
|
||||
cf.setTrustStorePassword("password");
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
LOG.info("Created client connection");
|
||||
assertNotNull(connection);
|
||||
connection.start();
|
||||
connection.stop();
|
||||
brokerStop();
|
||||
}
|
||||
|
||||
public void testFailoverSslConnection() throws Exception {
|
||||
// Create SSL/TLS connection with trusted cert from truststore.
|
||||
String sslUri = "ssl://localhost:61611";
|
||||
broker = createSslBroker(sslUri);
|
||||
assertNotNull(broker);
|
||||
|
||||
// This should create the connection.
|
||||
ActiveMQSslConnectionFactory cf = new ActiveMQSslConnectionFactory("failover:(" + sslUri + ")?maxReconnectAttempts=4");
|
||||
cf.setTrustStore("server.keystore");
|
||||
cf.setTrustStorePassword("password");
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
LOG.info("Created client connection");
|
||||
assertNotNull(connection);
|
||||
connection.start();
|
||||
connection.stop();
|
||||
|
||||
brokerStop();
|
||||
}
|
||||
|
||||
public void testFailoverSslConnectionWithKeyAndTrustManagers() throws Exception {
|
||||
String sslUri = "ssl://localhost:61611";
|
||||
broker = createSslBroker(sslUri);
|
||||
assertNotNull(broker);
|
||||
|
||||
ActiveMQSslConnectionFactory cf = new ActiveMQSslConnectionFactory("failover:(" + sslUri + ")?maxReconnectAttempts=4");
|
||||
cf.setKeyAndTrustManagers(getKeyManager(), getTrustManager(), new SecureRandom());
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
LOG.info("Created client connection");
|
||||
assertNotNull(connection);
|
||||
connection.start();
|
||||
connection.stop();
|
||||
|
||||
brokerStop();
|
||||
}
|
||||
|
||||
public void testNegativeCreateSslConnectionWithWrongPassword() throws Exception {
|
||||
// Create SSL/TLS connection with trusted cert from truststore.
|
||||
String sslUri = "ssl://localhost:61611";
|
||||
broker = createSslBroker(sslUri);
|
||||
assertNotNull(broker);
|
||||
|
||||
// This should FAIL to connect, due to wrong password.
|
||||
ActiveMQSslConnectionFactory cf = new ActiveMQSslConnectionFactory(sslUri);
|
||||
cf.setTrustStore("server.keystore");
|
||||
cf.setTrustStorePassword("wrongPassword");
|
||||
try {
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
}
|
||||
catch (javax.jms.JMSException ignore) {
|
||||
// Expected exception
|
||||
LOG.info("Expected java.io.Exception [" + ignore + "]");
|
||||
}
|
||||
assertNull(connection);
|
||||
|
||||
brokerStop();
|
||||
}
|
||||
|
||||
public void testNegativeCreateSslConnectionWithWrongCert() throws Exception {
|
||||
// Create SSL/TLS connection with trusted cert from truststore.
|
||||
String sslUri = "ssl://localhost:61611";
|
||||
broker = createSslBroker(sslUri);
|
||||
assertNotNull(broker);
|
||||
|
||||
// This should FAIL to connect, due to wrong password.
|
||||
ActiveMQSslConnectionFactory cf = new ActiveMQSslConnectionFactory(sslUri);
|
||||
cf.setTrustStore("dummy.keystore");
|
||||
cf.setTrustStorePassword("password");
|
||||
try {
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
}
|
||||
catch (javax.jms.JMSException ignore) {
|
||||
// Expected exception
|
||||
LOG.info("Expected SSLHandshakeException [" + ignore + "]");
|
||||
}
|
||||
assertNull(connection);
|
||||
|
||||
brokerStop();
|
||||
}
|
||||
|
||||
protected BrokerService createBroker(String uri) throws Exception {
|
||||
// Start up a broker with a tcp connector.
|
||||
BrokerService service = new BrokerService();
|
||||
service.setPersistent(false);
|
||||
service.setUseJmx(false);
|
||||
service.addConnector(uri);
|
||||
service.start();
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
protected BrokerService createSslBroker(String uri) throws Exception {
|
||||
|
||||
// http://java.sun.com/javase/javaseforbusiness/docs/TLSReadme.html
|
||||
// work around: javax.net.ssl.SSLHandshakeException: renegotiation is not allowed
|
||||
//System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
|
||||
|
||||
SslBrokerService service = new SslBrokerService();
|
||||
service.setPersistent(false);
|
||||
|
||||
service.setupSsl(KEYSTORE_TYPE, PASSWORD, SERVER_KEYSTORE);
|
||||
|
||||
service.start();
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
protected void brokerStop() throws Exception {
|
||||
broker.stop();
|
||||
}
|
||||
|
||||
public static TrustManager[] getTrustManager() throws Exception {
|
||||
TrustManager[] trustStoreManagers = null;
|
||||
KeyStore trustedCertStore = KeyStore.getInstance(ActiveMQSslConnectionFactoryTest.KEYSTORE_TYPE);
|
||||
|
||||
trustedCertStore.load(new FileInputStream(ActiveMQSslConnectionFactoryTest.TRUST_KEYSTORE), null);
|
||||
TrustManagerFactory tmf =
|
||||
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
|
||||
tmf.init(trustedCertStore);
|
||||
trustStoreManagers = tmf.getTrustManagers();
|
||||
return trustStoreManagers;
|
||||
}
|
||||
|
||||
public static KeyManager[] getKeyManager() throws Exception {
|
||||
KeyManagerFactory kmf =
|
||||
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
KeyStore ks = KeyStore.getInstance(ActiveMQSslConnectionFactoryTest.KEYSTORE_TYPE);
|
||||
KeyManager[] keystoreManagers = null;
|
||||
|
||||
byte[] sslCert = loadClientCredential(ActiveMQSslConnectionFactoryTest.SERVER_KEYSTORE);
|
||||
|
||||
|
||||
if (sslCert != null && sslCert.length > 0) {
|
||||
ByteArrayInputStream bin = new ByteArrayInputStream(sslCert);
|
||||
ks.load(bin, ActiveMQSslConnectionFactoryTest.PASSWORD.toCharArray());
|
||||
kmf.init(ks, ActiveMQSslConnectionFactoryTest.PASSWORD.toCharArray());
|
||||
keystoreManagers = kmf.getKeyManagers();
|
||||
}
|
||||
return keystoreManagers;
|
||||
}
|
||||
|
||||
private static byte[] loadClientCredential(String fileName) throws IOException {
|
||||
if (fileName == null) {
|
||||
return null;
|
||||
}
|
||||
FileInputStream in = new FileInputStream(fileName);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] buf = new byte[512];
|
||||
int i = in.read(buf);
|
||||
while (i > 0) {
|
||||
out.write(buf, 0, i);
|
||||
i = in.read(buf);
|
||||
}
|
||||
in.close();
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,584 @@
|
|||
/**
|
||||
* 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.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.jms.XAConnection;
|
||||
import javax.jms.XAQueueConnection;
|
||||
import javax.jms.XASession;
|
||||
import javax.jms.XATopicConnection;
|
||||
import javax.transaction.xa.XAException;
|
||||
import javax.transaction.xa.XAResource;
|
||||
import javax.transaction.xa.Xid;
|
||||
|
||||
import org.apache.activemq.broker.BrokerFactory;
|
||||
import org.apache.activemq.broker.BrokerRegistry;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.TransactionBroker;
|
||||
import org.apache.activemq.broker.TransportConnection;
|
||||
import org.apache.activemq.broker.TransportConnector;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTextMessage;
|
||||
import org.apache.activemq.command.ConnectionId;
|
||||
import org.apache.activemq.command.TransactionInfo;
|
||||
import org.apache.activemq.command.XATransactionId;
|
||||
import org.apache.activemq.management.JMSConnectionStatsImpl;
|
||||
import org.apache.activemq.transport.failover.FailoverTransport;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ActiveMQXAConnectionFactoryTest extends CombinationTestSupport {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ActiveMQXAConnectionFactoryTest.class);
|
||||
long txGenerator = System.currentTimeMillis();
|
||||
private ActiveMQConnection connection;
|
||||
private BrokerService broker;
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
// Try our best to close any previously opend connection.
|
||||
try {
|
||||
connection.close();
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
// Try our best to stop any previously started broker.
|
||||
try {
|
||||
broker.stop();
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testCopy() throws URISyntaxException, JMSException {
|
||||
ActiveMQXAConnectionFactory cf = new ActiveMQXAConnectionFactory("vm://localhost?");
|
||||
ActiveMQConnectionFactory copy = cf.copy();
|
||||
assertTrue("Should be an ActiveMQXAConnectionFactory", copy instanceof ActiveMQXAConnectionFactory);
|
||||
}
|
||||
|
||||
public void testUseURIToSetOptionsOnConnectionFactory() throws URISyntaxException, JMSException {
|
||||
ActiveMQXAConnectionFactory cf = new ActiveMQXAConnectionFactory(
|
||||
"vm://localhost?jms.useAsyncSend=true");
|
||||
assertTrue(cf.isUseAsyncSend());
|
||||
// the broker url have been adjusted.
|
||||
assertEquals("vm://localhost", cf.getBrokerURL());
|
||||
|
||||
cf = new ActiveMQXAConnectionFactory("vm://localhost?jms.useAsyncSend=false");
|
||||
assertFalse(cf.isUseAsyncSend());
|
||||
// the broker url have been adjusted.
|
||||
assertEquals("vm://localhost", cf.getBrokerURL());
|
||||
|
||||
cf = new ActiveMQXAConnectionFactory("vm:(broker:()/localhost)?jms.useAsyncSend=true");
|
||||
assertTrue(cf.isUseAsyncSend());
|
||||
// the broker url have been adjusted.
|
||||
assertEquals("vm:(broker:()/localhost)", cf.getBrokerURL());
|
||||
|
||||
cf = new ActiveMQXAConnectionFactory(
|
||||
"vm://localhost?jms.redeliveryPolicy.maximumRedeliveries=10&" +
|
||||
"jms.redeliveryPolicy.initialRedeliveryDelay=10000&" +
|
||||
"jms.redeliveryPolicy.redeliveryDelay=10000&" +
|
||||
"jms.redeliveryPolicy.useExponentialBackOff=true&" +
|
||||
"jms.redeliveryPolicy.backOffMultiplier=2");
|
||||
assertEquals(10, cf.getRedeliveryPolicy().getMaximumRedeliveries());
|
||||
assertEquals(10000, cf.getRedeliveryPolicy().getInitialRedeliveryDelay());
|
||||
assertEquals(10000, cf.getRedeliveryPolicy().getRedeliveryDelay());
|
||||
assertEquals(true, cf.getRedeliveryPolicy().isUseExponentialBackOff());
|
||||
assertEquals(2.0, cf.getRedeliveryPolicy().getBackOffMultiplier(), 0.1);
|
||||
|
||||
// the broker url have been adjusted.
|
||||
assertEquals("vm://localhost", cf.getBrokerURL());
|
||||
}
|
||||
|
||||
public void testCreateVMConnectionWithEmbdeddBroker() throws URISyntaxException, JMSException {
|
||||
ActiveMQXAConnectionFactory cf = new ActiveMQXAConnectionFactory("vm://myBroker?broker.persistent=false");
|
||||
// Make sure the broker is not created until the connection is
|
||||
// instantiated.
|
||||
assertNull(BrokerRegistry.getInstance().lookup("myBroker"));
|
||||
connection = (ActiveMQConnection) cf.createConnection();
|
||||
// This should create the connection.
|
||||
assertNotNull(connection);
|
||||
// Verify the broker was created.
|
||||
assertNotNull(BrokerRegistry.getInstance().lookup("myBroker"));
|
||||
connection.close();
|
||||
// Verify the broker was destroyed.
|
||||
assertNull(BrokerRegistry.getInstance().lookup("myBroker"));
|
||||
|
||||
connection.close();
|
||||
}
|
||||
|
||||
public void testGetBrokerName() throws URISyntaxException, JMSException {
|
||||
ActiveMQXAConnectionFactory cf = new ActiveMQXAConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
connection = (ActiveMQConnection)cf.createConnection();
|
||||
connection.start();
|
||||
|
||||
String brokerName = connection.getBrokerName();
|
||||
LOG.info("Got broker name: " + brokerName);
|
||||
|
||||
assertNotNull("No broker name available!", brokerName);
|
||||
connection.close();
|
||||
}
|
||||
|
||||
public void testCreateTcpConnectionUsingAllocatedPort() throws Exception {
|
||||
assertCreateConnection("tcp://localhost:0?wireFormat.tcpNoDelayEnabled=true");
|
||||
}
|
||||
|
||||
public void testCreateTcpConnectionUsingKnownPort() throws Exception {
|
||||
assertCreateConnection("tcp://localhost:61610?wireFormat.tcpNoDelayEnabled=true");
|
||||
}
|
||||
|
||||
public void testIsSameRM() throws URISyntaxException, JMSException, XAException {
|
||||
|
||||
XAConnection connection1 = null;
|
||||
XAConnection connection2 = null;
|
||||
try {
|
||||
ActiveMQXAConnectionFactory cf1 = new ActiveMQXAConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
connection1 = (XAConnection)cf1.createConnection();
|
||||
XASession session1 = connection1.createXASession();
|
||||
XAResource resource1 = session1.getXAResource();
|
||||
|
||||
ActiveMQXAConnectionFactory cf2 = new ActiveMQXAConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
connection2 = (XAConnection)cf2.createConnection();
|
||||
XASession session2 = connection2.createXASession();
|
||||
XAResource resource2 = session2.getXAResource();
|
||||
|
||||
assertTrue(resource1.isSameRM(resource2));
|
||||
session1.close();
|
||||
session2.close();
|
||||
} finally {
|
||||
if (connection1 != null) {
|
||||
try {
|
||||
connection1.close();
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (connection2 != null) {
|
||||
try {
|
||||
connection2.close();
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testIsSameRMOverride() throws URISyntaxException, JMSException, XAException {
|
||||
|
||||
XAConnection connection1 = null;
|
||||
XAConnection connection2 = null;
|
||||
try {
|
||||
ActiveMQXAConnectionFactory cf1 = new ActiveMQXAConnectionFactory("vm://localhost?broker.persistent=false&jms.rmIdFromConnectionId=true");
|
||||
connection1 = (XAConnection)cf1.createConnection();
|
||||
XASession session1 = connection1.createXASession();
|
||||
XAResource resource1 = session1.getXAResource();
|
||||
|
||||
ActiveMQXAConnectionFactory cf2 = new ActiveMQXAConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
connection2 = (XAConnection)cf2.createConnection();
|
||||
XASession session2 = connection2.createXASession();
|
||||
XAResource resource2 = session2.getXAResource();
|
||||
|
||||
assertFalse(resource1.isSameRM(resource2));
|
||||
|
||||
// ensure identity is preserved
|
||||
XASession session1a = connection1.createXASession();
|
||||
assertTrue(resource1.isSameRM(session1a.getXAResource()));
|
||||
session1.close();
|
||||
session2.close();
|
||||
} finally {
|
||||
if (connection1 != null) {
|
||||
try {
|
||||
connection1.close();
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (connection2 != null) {
|
||||
try {
|
||||
connection2.close();
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testVanilaTransactionalProduceReceive() throws Exception {
|
||||
|
||||
XAConnection connection1 = null;
|
||||
try {
|
||||
ActiveMQXAConnectionFactory cf1 = new ActiveMQXAConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
connection1 = (XAConnection)cf1.createConnection();
|
||||
connection1.start();
|
||||
XASession session = connection1.createXASession();
|
||||
XAResource resource = session.getXAResource();
|
||||
Destination dest = new ActiveMQQueue(getName());
|
||||
|
||||
// publish a message
|
||||
Xid tid = createXid();
|
||||
resource.start(tid, XAResource.TMNOFLAGS);
|
||||
MessageProducer producer = session.createProducer(dest);
|
||||
ActiveMQTextMessage message = new ActiveMQTextMessage();
|
||||
message.setText(getName());
|
||||
producer.send(message);
|
||||
resource.end(tid, XAResource.TMSUCCESS);
|
||||
resource.commit(tid, true);
|
||||
session.close();
|
||||
|
||||
session = connection1.createXASession();
|
||||
MessageConsumer consumer = session.createConsumer(dest);
|
||||
tid = createXid();
|
||||
resource = session.getXAResource();
|
||||
resource.start(tid, XAResource.TMNOFLAGS);
|
||||
TextMessage receivedMessage = (TextMessage) consumer.receive(1000);
|
||||
assertNotNull(receivedMessage);
|
||||
assertEquals(getName(), receivedMessage.getText());
|
||||
resource.end(tid, XAResource.TMSUCCESS);
|
||||
resource.commit(tid, true);
|
||||
session.close();
|
||||
|
||||
} finally {
|
||||
if (connection1 != null) {
|
||||
try {
|
||||
connection1.close();
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testConsumerCloseTransactionalSendReceive() throws Exception {
|
||||
|
||||
ActiveMQXAConnectionFactory cf1 = new ActiveMQXAConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
XAConnection connection1 = (XAConnection)cf1.createConnection();
|
||||
connection1.start();
|
||||
XASession session = connection1.createXASession();
|
||||
XAResource resource = session.getXAResource();
|
||||
Destination dest = new ActiveMQQueue(getName());
|
||||
|
||||
// publish a message
|
||||
Xid tid = createXid();
|
||||
resource.start(tid, XAResource.TMNOFLAGS);
|
||||
MessageProducer producer = session.createProducer(dest);
|
||||
ActiveMQTextMessage message = new ActiveMQTextMessage();
|
||||
message.setText(getName());
|
||||
producer.send(message);
|
||||
producer.close();
|
||||
resource.end(tid, XAResource.TMSUCCESS);
|
||||
resource.commit(tid, true);
|
||||
session.close();
|
||||
|
||||
session = connection1.createXASession();
|
||||
MessageConsumer consumer = session.createConsumer(dest);
|
||||
tid = createXid();
|
||||
resource = session.getXAResource();
|
||||
resource.start(tid, XAResource.TMNOFLAGS);
|
||||
TextMessage receivedMessage = (TextMessage) consumer.receive(1000);
|
||||
consumer.close();
|
||||
assertNotNull(receivedMessage);
|
||||
assertEquals(getName(), receivedMessage.getText());
|
||||
resource.end(tid, XAResource.TMSUCCESS);
|
||||
resource.commit(tid, true);
|
||||
|
||||
session = connection1.createXASession();
|
||||
consumer = session.createConsumer(dest);
|
||||
tid = createXid();
|
||||
resource = session.getXAResource();
|
||||
resource.start(tid, XAResource.TMNOFLAGS);
|
||||
assertNull(consumer.receive(1000));
|
||||
resource.end(tid, XAResource.TMSUCCESS);
|
||||
resource.commit(tid, true);
|
||||
|
||||
}
|
||||
|
||||
public void testSessionCloseTransactionalSendReceive() throws Exception {
|
||||
|
||||
ActiveMQXAConnectionFactory cf1 = new ActiveMQXAConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
XAConnection connection1 = (XAConnection)cf1.createConnection();
|
||||
connection1.start();
|
||||
XASession session = connection1.createXASession();
|
||||
XAResource resource = session.getXAResource();
|
||||
Destination dest = new ActiveMQQueue(getName());
|
||||
|
||||
// publish a message
|
||||
Xid tid = createXid();
|
||||
resource.start(tid, XAResource.TMNOFLAGS);
|
||||
MessageProducer producer = session.createProducer(dest);
|
||||
ActiveMQTextMessage message = new ActiveMQTextMessage();
|
||||
message.setText(getName());
|
||||
producer.send(message);
|
||||
session.close();
|
||||
resource.end(tid, XAResource.TMSUCCESS);
|
||||
resource.commit(tid, true);
|
||||
|
||||
|
||||
session = connection1.createXASession();
|
||||
MessageConsumer consumer = session.createConsumer(dest);
|
||||
tid = createXid();
|
||||
resource = session.getXAResource();
|
||||
resource.start(tid, XAResource.TMNOFLAGS);
|
||||
TextMessage receivedMessage = (TextMessage) consumer.receive(1000);
|
||||
session.close();
|
||||
assertNotNull(receivedMessage);
|
||||
assertEquals(getName(), receivedMessage.getText());
|
||||
resource.end(tid, XAResource.TMSUCCESS);
|
||||
resource.commit(tid, true);
|
||||
|
||||
session = connection1.createXASession();
|
||||
consumer = session.createConsumer(dest);
|
||||
tid = createXid();
|
||||
resource = session.getXAResource();
|
||||
resource.start(tid, XAResource.TMNOFLAGS);
|
||||
assertNull(consumer.receive(1000));
|
||||
resource.end(tid, XAResource.TMSUCCESS);
|
||||
resource.commit(tid, true);
|
||||
}
|
||||
|
||||
|
||||
public void testReadonlyNoLeak() throws Exception {
|
||||
final String brokerName = "readOnlyNoLeak";
|
||||
BrokerService broker = BrokerFactory.createBroker(new URI("broker:(tcp://localhost:0)/" + brokerName));
|
||||
broker.setPersistent(false);
|
||||
broker.start();
|
||||
ActiveMQXAConnectionFactory cf1 = new ActiveMQXAConnectionFactory("failover:(" + broker.getTransportConnectors().get(0).getConnectUri() + ")");
|
||||
cf1.setStatsEnabled(true);
|
||||
ActiveMQXAConnection xaConnection = (ActiveMQXAConnection)cf1.createConnection();
|
||||
xaConnection.start();
|
||||
XASession session = xaConnection.createXASession();
|
||||
XAResource resource = session.getXAResource();
|
||||
Xid tid = createXid();
|
||||
resource.start(tid, XAResource.TMNOFLAGS);
|
||||
session.close();
|
||||
resource.end(tid, XAResource.TMSUCCESS);
|
||||
resource.commit(tid, true);
|
||||
|
||||
assertTransactionGoneFromBroker(tid);
|
||||
assertTransactionGoneFromConnection(brokerName, xaConnection.getClientID(), xaConnection.getConnectionInfo().getConnectionId(), tid);
|
||||
assertSessionGone(xaConnection, session);
|
||||
assertTransactionGoneFromFailoverState(xaConnection, tid);
|
||||
|
||||
// two phase
|
||||
session = xaConnection.createXASession();
|
||||
resource = session.getXAResource();
|
||||
tid = createXid();
|
||||
resource.start(tid, XAResource.TMNOFLAGS);
|
||||
session.close();
|
||||
resource.end(tid, XAResource.TMSUCCESS);
|
||||
assertEquals(XAResource.XA_RDONLY, resource.prepare(tid));
|
||||
|
||||
// no need for a commit on read only
|
||||
assertTransactionGoneFromBroker(tid);
|
||||
assertTransactionGoneFromConnection(brokerName, xaConnection.getClientID(), xaConnection.getConnectionInfo().getConnectionId(), tid);
|
||||
assertSessionGone(xaConnection, session);
|
||||
assertTransactionGoneFromFailoverState(xaConnection, tid);
|
||||
|
||||
xaConnection.close();
|
||||
broker.stop();
|
||||
|
||||
}
|
||||
|
||||
public void testCloseSendConnection() throws Exception {
|
||||
String brokerName = "closeSend";
|
||||
BrokerService broker = BrokerFactory.createBroker(new URI("broker:(tcp://localhost:0)/" + brokerName));
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
ActiveMQXAConnectionFactory cf = new ActiveMQXAConnectionFactory(broker.getTransportConnectors().get(0).getConnectUri());
|
||||
XAConnection connection = (XAConnection)cf.createConnection();
|
||||
connection.start();
|
||||
XASession session = connection.createXASession();
|
||||
XAResource resource = session.getXAResource();
|
||||
Destination dest = new ActiveMQQueue(getName());
|
||||
|
||||
// publish a message
|
||||
Xid tid = createXid();
|
||||
resource.start(tid, XAResource.TMNOFLAGS);
|
||||
MessageProducer producer = session.createProducer(dest);
|
||||
ActiveMQTextMessage message = new ActiveMQTextMessage();
|
||||
message.setText(getName());
|
||||
producer.send(message);
|
||||
|
||||
connection.close();
|
||||
|
||||
assertTransactionGoneFromBroker(tid);
|
||||
|
||||
broker.stop();
|
||||
}
|
||||
|
||||
public void testExceptionAfterClose() throws Exception {
|
||||
|
||||
ActiveMQXAConnectionFactory cf1 = new ActiveMQXAConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
XAConnection connection1 = (XAConnection)cf1.createConnection();
|
||||
connection1.start();
|
||||
|
||||
XASession session = connection1.createXASession();
|
||||
session.close();
|
||||
try {
|
||||
session.commit();
|
||||
fail("expect exception after close");
|
||||
} catch (javax.jms.IllegalStateException expected) {}
|
||||
|
||||
try {
|
||||
session.rollback();
|
||||
fail("expect exception after close");
|
||||
} catch (javax.jms.IllegalStateException expected) {}
|
||||
|
||||
try {
|
||||
session.getTransacted();
|
||||
fail("expect exception after close");
|
||||
} catch (javax.jms.IllegalStateException expected) {}
|
||||
}
|
||||
|
||||
public void testRollbackXaErrorCode() throws Exception {
|
||||
String brokerName = "rollbackErrorCode";
|
||||
BrokerService broker = BrokerFactory.createBroker(new URI("broker:(tcp://localhost:0)/" + brokerName));
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
ActiveMQXAConnectionFactory cf = new ActiveMQXAConnectionFactory(broker.getTransportConnectors().get(0).getConnectUri());
|
||||
XAConnection connection = (XAConnection)cf.createConnection();
|
||||
connection.start();
|
||||
XASession session = connection.createXASession();
|
||||
XAResource resource = session.getXAResource();
|
||||
|
||||
Xid tid = createXid();
|
||||
try {
|
||||
resource.rollback(tid);
|
||||
fail("Expected xa exception on no tx");
|
||||
} catch (XAException expected) {
|
||||
LOG.info("got expected xa", expected);
|
||||
assertEquals("no tx", XAException.XAER_NOTA, expected.errorCode);
|
||||
}
|
||||
connection.close();
|
||||
broker.stop();
|
||||
}
|
||||
|
||||
private void assertTransactionGoneFromFailoverState(
|
||||
ActiveMQXAConnection connection1, Xid tid) throws Exception {
|
||||
|
||||
FailoverTransport transport = (FailoverTransport) connection1.getTransport().narrow(FailoverTransport.class);
|
||||
TransactionInfo info = new TransactionInfo(connection1.getConnectionInfo().getConnectionId(), new XATransactionId(tid), TransactionInfo.COMMIT_ONE_PHASE);
|
||||
assertNull("transaction should not exist in the state tracker",
|
||||
transport.getStateTracker().processCommitTransactionOnePhase(info));
|
||||
}
|
||||
|
||||
private void assertSessionGone(ActiveMQXAConnection connection1,
|
||||
XASession session) {
|
||||
JMSConnectionStatsImpl stats = (JMSConnectionStatsImpl)connection1.getStats();
|
||||
// should be no dangling sessions maintained by the transaction
|
||||
assertEquals("should be no sessions", 0, stats.getSessions().length);
|
||||
}
|
||||
|
||||
private void assertTransactionGoneFromConnection(String brokerName, String clientId, ConnectionId connectionId, Xid tid) throws Exception {
|
||||
BrokerService broker = BrokerRegistry.getInstance().lookup(brokerName);
|
||||
CopyOnWriteArrayList<TransportConnection> connections = broker.getTransportConnectors().get(0).getConnections();
|
||||
for (TransportConnection connection: connections) {
|
||||
if (connection.getConnectionId().equals(clientId)) {
|
||||
try {
|
||||
connection.processPrepareTransaction(new TransactionInfo(connectionId, new XATransactionId(tid), TransactionInfo.PREPARE));
|
||||
fail("did not get expected excepton on missing transaction, it must be still there in error!");
|
||||
} catch (IllegalStateException expectedOnNoTransaction) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void assertTransactionGoneFromBroker(Xid tid) throws Exception {
|
||||
BrokerService broker = BrokerRegistry.getInstance().lookup("localhost");
|
||||
TransactionBroker transactionBroker = (TransactionBroker)broker.getBroker().getAdaptor(TransactionBroker.class);
|
||||
try {
|
||||
transactionBroker.getTransaction(null, new XATransactionId(tid), false);
|
||||
fail("expected exception on tx not found");
|
||||
} catch (XAException expectedOnNotFound) {
|
||||
}
|
||||
}
|
||||
|
||||
protected void assertCreateConnection(String uri) throws Exception {
|
||||
// Start up a broker with a tcp connector.
|
||||
broker = new BrokerService();
|
||||
broker.setPersistent(false);
|
||||
broker.setUseJmx(false);
|
||||
TransportConnector connector = broker.addConnector(uri);
|
||||
broker.start();
|
||||
|
||||
URI temp = new URI(uri);
|
||||
// URI connectURI = connector.getServer().getConnectURI();
|
||||
// TODO this sometimes fails when using the actual local host name
|
||||
URI currentURI = new URI(connector.getPublishableConnectString());
|
||||
|
||||
// sometimes the actual host name doesn't work in this test case
|
||||
// e.g. on OS X so lets use the original details but just use the actual
|
||||
// port
|
||||
URI connectURI = new URI(temp.getScheme(), temp.getUserInfo(), temp.getHost(), currentURI.getPort(),
|
||||
temp.getPath(), temp.getQuery(), temp.getFragment());
|
||||
|
||||
LOG.info("connection URI is: " + connectURI);
|
||||
|
||||
// This should create the connection.
|
||||
ActiveMQXAConnectionFactory cf = new ActiveMQXAConnectionFactory(connectURI);
|
||||
Connection connection = cf.createConnection();
|
||||
|
||||
assertXAConnection(connection);
|
||||
|
||||
assertNotNull(connection);
|
||||
connection.close();
|
||||
|
||||
connection = cf.createXAConnection();
|
||||
|
||||
assertXAConnection(connection);
|
||||
|
||||
assertNotNull(connection);
|
||||
}
|
||||
|
||||
private void assertXAConnection(Connection connection) {
|
||||
assertTrue("Should be an XAConnection", connection instanceof XAConnection);
|
||||
assertTrue("Should be an XATopicConnection", connection instanceof XATopicConnection);
|
||||
assertTrue("Should be an XAQueueConnection", connection instanceof XAQueueConnection);
|
||||
}
|
||||
|
||||
public Xid createXid() throws IOException {
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DataOutputStream os = new DataOutputStream(baos);
|
||||
os.writeLong(++txGenerator);
|
||||
os.close();
|
||||
final byte[] bs = baos.toByteArray();
|
||||
|
||||
return new Xid() {
|
||||
public int getFormatId() {
|
||||
return 86;
|
||||
}
|
||||
|
||||
public byte[] getGlobalTransactionId() {
|
||||
return bs;
|
||||
}
|
||||
|
||||
public byte[] getBranchQualifier() {
|
||||
return bs;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* 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.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.jms.JMSException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.broker.Broker;
|
||||
import org.apache.activemq.broker.BrokerFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.StubConnection;
|
||||
import org.apache.activemq.broker.TransportConnector;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ConnectionId;
|
||||
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.MessageDispatch;
|
||||
import org.apache.activemq.command.RemoveInfo;
|
||||
import org.apache.activemq.command.SessionInfo;
|
||||
import org.apache.activemq.transport.TransportFactory;
|
||||
|
||||
public class ClientTestSupport extends TestCase {
|
||||
|
||||
protected BrokerService broker;
|
||||
protected long idGenerator;
|
||||
|
||||
private ActiveMQConnectionFactory connFactory;
|
||||
private final String brokerURL = "vm://localhost?broker.persistent=false";
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
final AtomicBoolean connected = new AtomicBoolean(false);
|
||||
TransportConnector connector;
|
||||
|
||||
// Start up a broker with a tcp connector.
|
||||
try {
|
||||
broker = BrokerFactory.createBroker(new URI(this.brokerURL));
|
||||
broker.getBrokerName();
|
||||
connector = new TransportConnector(TransportFactory.bind(new URI(this.brokerURL))) {
|
||||
// Hook into the connector so we can assert that the server
|
||||
// accepted a connection.
|
||||
@Override
|
||||
protected org.apache.activemq.broker.Connection createConnection(org.apache.activemq.transport.Transport transport) throws IOException {
|
||||
connected.set(true);
|
||||
return super.createConnection(transport);
|
||||
}
|
||||
};
|
||||
broker.addConnector(connector);
|
||||
broker.start();
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new JMSException("Error creating broker " + e);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new JMSException("Error creating broker " + e);
|
||||
}
|
||||
|
||||
URI connectURI;
|
||||
connectURI = connector.getServer().getConnectURI();
|
||||
|
||||
// This should create the connection.
|
||||
connFactory = new ActiveMQConnectionFactory(connectURI);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public ActiveMQConnectionFactory getConnectionFactory() throws JMSException {
|
||||
if (this.connFactory == null) {
|
||||
throw new JMSException("ActiveMQConnectionFactory is null ");
|
||||
}
|
||||
return this.connFactory;
|
||||
}
|
||||
|
||||
// Helper Classes
|
||||
protected ConnectionInfo createConnectionInfo() throws Exception {
|
||||
ConnectionInfo info = new ConnectionInfo();
|
||||
info.setConnectionId(new ConnectionId("connection:" + (++idGenerator)));
|
||||
info.setClientId(info.getConnectionId().getValue());
|
||||
return info;
|
||||
}
|
||||
|
||||
protected SessionInfo createSessionInfo(ConnectionInfo connectionInfo) throws Exception {
|
||||
SessionInfo info = new SessionInfo(connectionInfo, ++idGenerator);
|
||||
return info;
|
||||
}
|
||||
|
||||
protected ConsumerInfo createConsumerInfo(SessionInfo sessionInfo, ActiveMQDestination destination) throws Exception {
|
||||
ConsumerInfo info = new ConsumerInfo(sessionInfo, ++idGenerator);
|
||||
info.setBrowser(false);
|
||||
info.setDestination(destination);
|
||||
info.setPrefetchSize(1000);
|
||||
info.setDispatchAsync(false);
|
||||
return info;
|
||||
}
|
||||
|
||||
protected RemoveInfo closeConsumerInfo(ConsumerInfo consumerInfo) {
|
||||
return consumerInfo.createRemoveCommand();
|
||||
}
|
||||
|
||||
protected MessageAck createAck(ConsumerInfo consumerInfo, Message msg, int count, byte ackType) {
|
||||
MessageAck ack = new MessageAck();
|
||||
ack.setAckType(ackType);
|
||||
ack.setConsumerId(consumerInfo.getConsumerId());
|
||||
ack.setDestination(msg.getDestination());
|
||||
ack.setLastMessageId(msg.getMessageId());
|
||||
ack.setMessageCount(count);
|
||||
return ack;
|
||||
}
|
||||
|
||||
protected Message receiveMessage(StubConnection connection, int maxWait) throws InterruptedException {
|
||||
while (true) {
|
||||
Object o = connection.getDispatchQueue().poll(maxWait, TimeUnit.MILLISECONDS);
|
||||
|
||||
if (o == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (o instanceof MessageDispatch) {
|
||||
MessageDispatch dispatch = (MessageDispatch)o;
|
||||
return dispatch.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Broker getBroker() throws Exception {
|
||||
return this.broker != null ? this.broker.getBroker() : null;
|
||||
}
|
||||
|
||||
public static void removeMessageStore() {
|
||||
if (System.getProperty("activemq.store.dir") != null) {
|
||||
recursiveDelete(new File(System.getProperty("activemq.store.dir")));
|
||||
}
|
||||
if (System.getProperty("derby.system.home") != null) {
|
||||
recursiveDelete(new File(System.getProperty("derby.system.home")));
|
||||
}
|
||||
}
|
||||
|
||||
public static void recursiveDelete(File f) {
|
||||
if (f.isDirectory()) {
|
||||
File[] files = f.listFiles();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
recursiveDelete(files[i]);
|
||||
}
|
||||
}
|
||||
f.delete();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,272 @@
|
|||
/**
|
||||
* 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.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Poor mans way of getting JUnit to run a test case through a few different
|
||||
* combinations of options. Usage: If you have a test case called testFoo what
|
||||
* you want to run through a few combinations, of of values for the attributes
|
||||
* age and color, you would something like: <code>
|
||||
* public void initCombosForTestFoo() {
|
||||
* addCombinationValues( "age", new Object[]{ new Integer(21), new Integer(30) } );
|
||||
* addCombinationValues( "color", new Object[]{"blue", "green"} );
|
||||
* }
|
||||
* </code>
|
||||
* The testFoo test case would be run for each possible combination of age and
|
||||
* color that you setup in the initCombosForTestFoo method. Before each
|
||||
* combination is run, the age and color fields of the test class are set to one
|
||||
* of the values defined. This is done before the normal setUp method is called.
|
||||
* If you want the test combinations to show up as separate test runs in the
|
||||
* JUnit reports, add a suite method to your test case similar to: <code>
|
||||
* public static Test suite() {
|
||||
* return suite(FooTest.class);
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class CombinationTestSupport extends AutoFailTestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CombinationTestSupport.class);
|
||||
|
||||
private final HashMap<String, ComboOption> comboOptions = new HashMap<String, ComboOption>();
|
||||
private boolean combosEvaluated;
|
||||
private Map<String, Object> options;
|
||||
protected File basedir;
|
||||
|
||||
static protected File basedir(Class<?> clazz) {
|
||||
try {
|
||||
ProtectionDomain protectionDomain = clazz.getProtectionDomain();
|
||||
return new File(new File(protectionDomain.getCodeSource().getLocation().getPath()), "../..").getCanonicalFile();
|
||||
} catch (IOException e) {
|
||||
return new File(".");
|
||||
}
|
||||
}
|
||||
|
||||
static class ComboOption {
|
||||
final String attribute;
|
||||
final LinkedHashSet<Object> values = new LinkedHashSet<Object>();
|
||||
|
||||
public ComboOption(String attribute, Collection<Object> options) {
|
||||
this.attribute = attribute;
|
||||
this.values.addAll(options);
|
||||
}
|
||||
}
|
||||
|
||||
public CombinationTestSupport() {
|
||||
basedir = basedir(getClass());
|
||||
}
|
||||
public void addCombinationValues(String attribute, Object[] options) {
|
||||
ComboOption co = this.comboOptions.get(attribute);
|
||||
if (co == null) {
|
||||
this.comboOptions.put(attribute, new ComboOption(attribute, Arrays.asList(options)));
|
||||
} else {
|
||||
co.values.addAll(Arrays.asList(options));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runBare() throws Throwable {
|
||||
if (combosEvaluated) {
|
||||
super.runBare();
|
||||
} else {
|
||||
CombinationTestSupport[] combinations = getCombinations();
|
||||
for (int i = 0; i < combinations.length; i++) {
|
||||
CombinationTestSupport test = combinations[i];
|
||||
if (getName() == null || getName().equals(test.getName())) {
|
||||
test.runBare();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setOptions(Map<String, Object> options) throws NoSuchFieldException, IllegalAccessException {
|
||||
this.options = options;
|
||||
for (Iterator<String> iterator = options.keySet().iterator(); iterator.hasNext();) {
|
||||
String attribute = iterator.next();
|
||||
Object value = options.get(attribute);
|
||||
try {
|
||||
Field field = getClass().getField(attribute);
|
||||
field.set(this, value);
|
||||
} catch (Throwable e) {
|
||||
try {
|
||||
boolean found = false;
|
||||
String setterName = "set" + attribute.substring(0, 1).toUpperCase() +
|
||||
attribute.substring(1);
|
||||
for(Method method : getClass().getMethods()) {
|
||||
if (method.getName().equals(setterName)) {
|
||||
method.invoke(this, value);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new NoSuchMethodError("No setter found for field: " + attribute);
|
||||
}
|
||||
|
||||
} catch(Throwable ex) {
|
||||
LOG.info("Could not set field '" + attribute + "' to value '" + value +
|
||||
"', make sure the field exists and is public or has a setter.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CombinationTestSupport[] getCombinations() {
|
||||
try {
|
||||
Method method = getClass().getMethod("initCombos", (Class[])null);
|
||||
method.invoke(this, (Object[])null);
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
|
||||
String name = getName().split(" ")[0];
|
||||
String comboSetupMethodName = "initCombosFor" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
|
||||
try {
|
||||
Method method = getClass().getMethod(comboSetupMethodName, (Class[])null);
|
||||
method.invoke(this, (Object[])null);
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
|
||||
try {
|
||||
ArrayList<HashMap<String, Object>> expandedOptions = new ArrayList<HashMap<String, Object>>();
|
||||
expandCombinations(new ArrayList<ComboOption>(comboOptions.values()), expandedOptions);
|
||||
|
||||
if (expandedOptions.isEmpty()) {
|
||||
combosEvaluated = true;
|
||||
return new CombinationTestSupport[] {this};
|
||||
} else {
|
||||
|
||||
ArrayList<CombinationTestSupport> result = new ArrayList<CombinationTestSupport>();
|
||||
// Run the test case for each possible combination
|
||||
for (Iterator<HashMap<String, Object>> iter = expandedOptions.iterator(); iter.hasNext();) {
|
||||
CombinationTestSupport combo = (CombinationTestSupport)TestSuite.createTest(getClass(), name);
|
||||
combo.combosEvaluated = true;
|
||||
combo.setOptions(iter.next());
|
||||
result.add(combo);
|
||||
}
|
||||
|
||||
CombinationTestSupport rc[] = new CombinationTestSupport[result.size()];
|
||||
result.toArray(rc);
|
||||
return rc;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
combosEvaluated = true;
|
||||
return new CombinationTestSupport[] {this};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void expandCombinations(List<ComboOption> optionsLeft, List<HashMap<String, Object>> expandedCombos) {
|
||||
if (!optionsLeft.isEmpty()) {
|
||||
HashMap<String, Object> map;
|
||||
if (comboOptions.size() == optionsLeft.size()) {
|
||||
map = new HashMap<String, Object>();
|
||||
expandedCombos.add(map);
|
||||
} else {
|
||||
map = expandedCombos.get(expandedCombos.size() - 1);
|
||||
}
|
||||
|
||||
LinkedList<ComboOption> l = new LinkedList<ComboOption>(optionsLeft);
|
||||
ComboOption comboOption = l.removeLast();
|
||||
int i = 0;
|
||||
if (comboOption.values.isEmpty() && !l.isEmpty()) {
|
||||
expandCombinations(l, expandedCombos);
|
||||
} else {
|
||||
for (Iterator<Object> iter = comboOption.values.iterator(); iter.hasNext();) {
|
||||
Object value = iter.next();
|
||||
if (i != 0) {
|
||||
map = new HashMap<String, Object>(map);
|
||||
expandedCombos.add(map);
|
||||
}
|
||||
map.put(comboOption.attribute, value);
|
||||
expandCombinations(l, expandedCombos);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Test suite(Class<? extends CombinationTestSupport> clazz) {
|
||||
TestSuite suite = new TestSuite();
|
||||
|
||||
ArrayList<String> names = new ArrayList<String>();
|
||||
Method[] methods = clazz.getMethods();
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
String name = methods[i].getName();
|
||||
if (names.contains(name) || !isPublicTestMethod(methods[i])) {
|
||||
continue;
|
||||
}
|
||||
names.add(name);
|
||||
Test test = TestSuite.createTest(clazz, name);
|
||||
if (test instanceof CombinationTestSupport) {
|
||||
CombinationTestSupport[] combinations = ((CombinationTestSupport)test).getCombinations();
|
||||
for (int j = 0; j < combinations.length; j++) {
|
||||
suite.addTest(combinations[j]);
|
||||
}
|
||||
} else {
|
||||
suite.addTest(test);
|
||||
}
|
||||
}
|
||||
return suite;
|
||||
}
|
||||
|
||||
private static boolean isPublicTestMethod(Method m) {
|
||||
return isTestMethod(m) && Modifier.isPublic(m.getModifiers());
|
||||
}
|
||||
|
||||
private static boolean isTestMethod(Method m) {
|
||||
String name = m.getName();
|
||||
Class<?>[] parameters = m.getParameterTypes();
|
||||
Class<?> returnType = m.getReturnType();
|
||||
return parameters.length == 0 && name.startsWith("test") && returnType.equals(Void.TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getName(false);
|
||||
}
|
||||
|
||||
public String getName(boolean original) {
|
||||
if (options != null && !original) {
|
||||
return super.getName() + " " + options;
|
||||
}
|
||||
return super.getName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* 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.JMSException;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ConnectionCleanupTest extends TestCase {
|
||||
|
||||
private ActiveMQConnection connection;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost");
|
||||
connection = (ActiveMQConnection)factory.createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
protected void tearDown() throws Exception {
|
||||
connection.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testChangeClientID() throws JMSException {
|
||||
|
||||
connection.setClientID("test");
|
||||
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
try {
|
||||
connection.setClientID("test");
|
||||
// fail("Should have received JMSException");
|
||||
} catch (JMSException e) {
|
||||
}
|
||||
|
||||
connection.cleanup();
|
||||
connection.setClientID("test");
|
||||
|
||||
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
try {
|
||||
connection.setClientID("test");
|
||||
// fail("Should have received JMSException");
|
||||
} catch (JMSException e) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* 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.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ConnectionCloseMultipleTimesConcurrentTest extends TestCase {
|
||||
|
||||
private ActiveMQConnection connection;
|
||||
private ExecutorService executor;
|
||||
private int size = 200;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
executor = Executors.newFixedThreadPool(20);
|
||||
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost");
|
||||
connection = (ActiveMQConnection)factory.createConnection();
|
||||
connection.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection.isStarted()) {
|
||||
connection.stop();
|
||||
}
|
||||
if (executor != null) {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws javax.jms.JMSException
|
||||
*/
|
||||
public void testCloseMultipleTimes() throws Exception {
|
||||
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
assertTrue(connection.isStarted());
|
||||
assertFalse(connection.isClosed());
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(size);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
executor.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
connection.close();
|
||||
|
||||
assertFalse(connection.isStarted());
|
||||
assertTrue(connection.isClosed());
|
||||
|
||||
latch.countDown();
|
||||
} catch (JMSException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
boolean zero = latch.await(20, TimeUnit.SECONDS);
|
||||
assertTrue("Should complete all", zero);
|
||||
|
||||
// should not fail calling again
|
||||
connection.close();
|
||||
|
||||
assertFalse(connection.isStarted());
|
||||
assertTrue(connection.isClosed());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* 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.JMSException;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ConnectionCloseMultipleTimesTest extends TestCase {
|
||||
|
||||
private ActiveMQConnection connection;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost");
|
||||
connection = (ActiveMQConnection)factory.createConnection();
|
||||
connection.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection.isStarted()) {
|
||||
connection.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws javax.jms.JMSException
|
||||
*/
|
||||
public void testCloseMultipleTimes() throws JMSException {
|
||||
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
assertTrue(connection.isStarted());
|
||||
assertFalse(connection.isClosed());
|
||||
|
||||
connection.close();
|
||||
|
||||
assertFalse(connection.isStarted());
|
||||
assertTrue(connection.isClosed());
|
||||
|
||||
// should not fail calling again
|
||||
connection.close();
|
||||
|
||||
assertFalse(connection.isStarted());
|
||||
assertTrue(connection.isClosed());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* 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.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ConsumerReceiveWithTimeoutTest extends TestSupport {
|
||||
|
||||
private Connection connection;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
connection = createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to check if consumer thread wakes up inside a receive(timeout) after
|
||||
* a message is dispatched to the consumer
|
||||
*
|
||||
* @throws javax.jms.JMSException
|
||||
*/
|
||||
public void testConsumerReceiveBeforeMessageDispatched() throws JMSException {
|
||||
|
||||
connection.start();
|
||||
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Queue queue = session.createQueue("test");
|
||||
|
||||
Thread t = new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
// wait for 10 seconds to allow consumer.receive to be run
|
||||
// first
|
||||
Thread.sleep(10000);
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.send(session.createTextMessage("Hello"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
t.start();
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(60000);
|
||||
assertNotNull(msg);
|
||||
session.close();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* 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.JMSException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class CreateConsumerButDontStartConnectionWarningTest extends JmsQueueSendReceiveTest {
|
||||
private static final transient Logger LOG = LoggerFactory.getLogger(CreateConsumerButDontStartConnectionWarningTest.class);
|
||||
|
||||
@Override
|
||||
protected void startConnection() throws JMSException {
|
||||
// don't start the connection
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertMessagesAreReceived() throws JMSException {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
LOG.warn("Caught: " + e, e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* A base class for a test case which creates an embedded broker and uses a connection and session
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class EmbeddedBrokerAndConnectionTestSupport extends EmbeddedBrokerTestSupport {
|
||||
protected Connection connection;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
connection = createConnection();
|
||||
connection.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/**
|
||||
* 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 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.springframework.jms.core.JmsTemplate;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Destination;
|
||||
|
||||
/**
|
||||
* A useful base class which creates and closes an embedded broker
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class EmbeddedBrokerTestSupport extends CombinationTestSupport {
|
||||
|
||||
protected BrokerService broker;
|
||||
// protected String bindAddress = "tcp://localhost:61616";
|
||||
protected String bindAddress = "vm://localhost";
|
||||
protected ConnectionFactory connectionFactory;
|
||||
protected boolean useTopic;
|
||||
protected ActiveMQDestination destination;
|
||||
protected JmsTemplate template;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
if (broker == null) {
|
||||
broker = createBroker();
|
||||
}
|
||||
startBroker();
|
||||
|
||||
connectionFactory = createConnectionFactory();
|
||||
|
||||
destination = createDestination();
|
||||
|
||||
template = createJmsTemplate();
|
||||
template.setDefaultDestination(destination);
|
||||
template.setPubSubDomain(useTopic);
|
||||
template.afterPropertiesSet();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
if (broker != null) {
|
||||
try {
|
||||
broker.stop();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*
|
||||
* @return newly created Destinaiton
|
||||
*/
|
||||
protected ActiveMQDestination createDestination() {
|
||||
return createDestination(getDestinationString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create the destination in either the queue or topic
|
||||
* space based on the value of the {@link #useTopic} field
|
||||
*/
|
||||
protected ActiveMQDestination createDestination(String subject) {
|
||||
if (useTopic) {
|
||||
return new ActiveMQTopic(subject);
|
||||
} else {
|
||||
return new ActiveMQQueue(subject);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the destination used in this test case
|
||||
*/
|
||||
protected String getDestinationString() {
|
||||
return getClass().getName() + "." + getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create a new {@link ConnectionFactory} instance
|
||||
*
|
||||
* @return a newly created connection factory
|
||||
*/
|
||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory(bindAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create a new broker
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService answer = new BrokerService();
|
||||
answer.setPersistent(isPersistent());
|
||||
answer.addConnector(bindAddress);
|
||||
return answer;
|
||||
}
|
||||
|
||||
protected void startBroker() throws Exception {
|
||||
broker.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether or not persistence should be used
|
||||
*/
|
||||
protected boolean isPersistent() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create a new connection
|
||||
*/
|
||||
protected Connection createConnection() throws Exception {
|
||||
return connectionFactory.createConnection();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
/**
|
||||
* 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.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
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.ActiveMQQueue;
|
||||
|
||||
public class ExclusiveConsumerStartupDestinationTest extends EmbeddedBrokerTestSupport{
|
||||
|
||||
private static final String VM_BROKER_URL = "vm://localhost";
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService answer = new BrokerService();
|
||||
answer.setPersistent(false);
|
||||
PolicyMap map = new PolicyMap();
|
||||
PolicyEntry entry = new PolicyEntry();
|
||||
entry.setAllConsumersExclusiveByDefault(true);
|
||||
map.setDefaultEntry(entry);
|
||||
answer.setDestinationPolicy(map);
|
||||
return answer;
|
||||
}
|
||||
|
||||
protected String getBrokerConfigUri() {
|
||||
return "org/apache/activemq/broker/exclusive-consumer-startup-destination.xml";
|
||||
}
|
||||
|
||||
private Connection createConnection(final boolean start) throws JMSException {
|
||||
ConnectionFactory cf = new ActiveMQConnectionFactory(VM_BROKER_URL);
|
||||
Connection conn = cf.createConnection();
|
||||
if (start) {
|
||||
conn.start();
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
|
||||
public void testExclusiveConsumerSelectedCreatedFirst() throws JMSException, InterruptedException {
|
||||
Connection conn = createConnection(true);
|
||||
|
||||
Session exclusiveSession = null;
|
||||
Session fallbackSession = null;
|
||||
Session senderSession = null;
|
||||
|
||||
try {
|
||||
|
||||
exclusiveSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
fallbackSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
senderSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
ActiveMQQueue exclusiveQueue = new ActiveMQQueue("TEST.QUEUE1");
|
||||
MessageConsumer exclusiveConsumer = exclusiveSession.createConsumer(exclusiveQueue);
|
||||
|
||||
ActiveMQQueue fallbackQueue = new ActiveMQQueue("TEST.QUEUE1");
|
||||
MessageConsumer fallbackConsumer = fallbackSession.createConsumer(fallbackQueue);
|
||||
|
||||
ActiveMQQueue senderQueue = new ActiveMQQueue("TEST.QUEUE1");
|
||||
|
||||
MessageProducer producer = senderSession.createProducer(senderQueue);
|
||||
|
||||
Message msg = senderSession.createTextMessage("test");
|
||||
producer.send(msg);
|
||||
// TODO need two send a 2nd message - bug AMQ-1024
|
||||
// producer.send(msg);
|
||||
Thread.sleep(100);
|
||||
|
||||
// Verify exclusive consumer receives the message.
|
||||
assertNotNull(exclusiveConsumer.receive(100));
|
||||
assertNull(fallbackConsumer.receive(100));
|
||||
} finally {
|
||||
fallbackSession.close();
|
||||
senderSession.close();
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void testFailoverToAnotherExclusiveConsumerCreatedFirst() throws JMSException,
|
||||
InterruptedException {
|
||||
Connection conn = createConnection(true);
|
||||
|
||||
Session exclusiveSession1 = null;
|
||||
Session exclusiveSession2 = null;
|
||||
Session fallbackSession = null;
|
||||
Session senderSession = null;
|
||||
|
||||
try {
|
||||
|
||||
exclusiveSession1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
exclusiveSession2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
fallbackSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
senderSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
// This creates the exclusive consumer first which avoids AMQ-1024
|
||||
// bug.
|
||||
ActiveMQQueue exclusiveQueue = new ActiveMQQueue("TEST.QUEUE2");
|
||||
MessageConsumer exclusiveConsumer1 = exclusiveSession1.createConsumer(exclusiveQueue);
|
||||
MessageConsumer exclusiveConsumer2 = exclusiveSession2.createConsumer(exclusiveQueue);
|
||||
|
||||
ActiveMQQueue fallbackQueue = new ActiveMQQueue("TEST.QUEUE2");
|
||||
MessageConsumer fallbackConsumer = fallbackSession.createConsumer(fallbackQueue);
|
||||
|
||||
ActiveMQQueue senderQueue = new ActiveMQQueue("TEST.QUEUE2");
|
||||
|
||||
MessageProducer producer = senderSession.createProducer(senderQueue);
|
||||
|
||||
Message msg = senderSession.createTextMessage("test");
|
||||
producer.send(msg);
|
||||
Thread.sleep(100);
|
||||
|
||||
// Verify exclusive consumer receives the message.
|
||||
assertNotNull(exclusiveConsumer1.receive(100));
|
||||
assertNull(exclusiveConsumer2.receive(100));
|
||||
assertNull(fallbackConsumer.receive(100));
|
||||
|
||||
// Close the exclusive consumer to verify the non-exclusive consumer
|
||||
// takes over
|
||||
exclusiveConsumer1.close();
|
||||
|
||||
producer.send(msg);
|
||||
producer.send(msg);
|
||||
|
||||
assertNotNull("Should have received a message", exclusiveConsumer2.receive(100));
|
||||
assertNull("Should not have received a message", fallbackConsumer.receive(100));
|
||||
|
||||
} finally {
|
||||
fallbackSession.close();
|
||||
senderSession.close();
|
||||
conn.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testFailoverToNonExclusiveConsumer() throws JMSException, InterruptedException {
|
||||
Connection conn = createConnection(true);
|
||||
|
||||
Session exclusiveSession = null;
|
||||
Session fallbackSession = null;
|
||||
Session senderSession = null;
|
||||
|
||||
try {
|
||||
|
||||
exclusiveSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
fallbackSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
senderSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
// This creates the exclusive consumer first which avoids AMQ-1024
|
||||
// bug.
|
||||
ActiveMQQueue exclusiveQueue = new ActiveMQQueue("TEST.QUEUE3");
|
||||
MessageConsumer exclusiveConsumer = exclusiveSession.createConsumer(exclusiveQueue);
|
||||
|
||||
ActiveMQQueue fallbackQueue = new ActiveMQQueue("TEST.QUEUE3");
|
||||
MessageConsumer fallbackConsumer = fallbackSession.createConsumer(fallbackQueue);
|
||||
|
||||
ActiveMQQueue senderQueue = new ActiveMQQueue("TEST.QUEUE3");
|
||||
|
||||
MessageProducer producer = senderSession.createProducer(senderQueue);
|
||||
|
||||
Message msg = senderSession.createTextMessage("test");
|
||||
producer.send(msg);
|
||||
Thread.sleep(100);
|
||||
|
||||
// Verify exclusive consumer receives the message.
|
||||
assertNotNull(exclusiveConsumer.receive(100));
|
||||
assertNull(fallbackConsumer.receive(100));
|
||||
|
||||
// Close the exclusive consumer to verify the non-exclusive consumer
|
||||
// takes over
|
||||
exclusiveConsumer.close();
|
||||
|
||||
producer.send(msg);
|
||||
|
||||
assertNotNull(fallbackConsumer.receive(100));
|
||||
|
||||
} finally {
|
||||
fallbackSession.close();
|
||||
senderSession.close();
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,357 @@
|
|||
/**
|
||||
* 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.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
|
||||
public class ExclusiveConsumerTest extends TestCase {
|
||||
|
||||
private static final String VM_BROKER_URL = "vm://localhost?broker.persistent=false&broker.useJmx=true";
|
||||
|
||||
public ExclusiveConsumerTest(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private Connection createConnection(final boolean start) throws JMSException {
|
||||
ConnectionFactory cf = new ActiveMQConnectionFactory(VM_BROKER_URL);
|
||||
Connection conn = cf.createConnection();
|
||||
if (start) {
|
||||
conn.start();
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
|
||||
public void testExclusiveConsumerSelectedCreatedFirst() throws JMSException, InterruptedException {
|
||||
Connection conn = createConnection(true);
|
||||
|
||||
Session exclusiveSession = null;
|
||||
Session fallbackSession = null;
|
||||
Session senderSession = null;
|
||||
|
||||
try {
|
||||
|
||||
exclusiveSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
fallbackSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
senderSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
ActiveMQQueue exclusiveQueue = new ActiveMQQueue("TEST.QUEUE1?consumer.exclusive=true");
|
||||
MessageConsumer exclusiveConsumer = exclusiveSession.createConsumer(exclusiveQueue);
|
||||
|
||||
ActiveMQQueue fallbackQueue = new ActiveMQQueue("TEST.QUEUE1");
|
||||
MessageConsumer fallbackConsumer = fallbackSession.createConsumer(fallbackQueue);
|
||||
|
||||
ActiveMQQueue senderQueue = new ActiveMQQueue("TEST.QUEUE1");
|
||||
|
||||
MessageProducer producer = senderSession.createProducer(senderQueue);
|
||||
|
||||
Message msg = senderSession.createTextMessage("test");
|
||||
producer.send(msg);
|
||||
// TODO need two send a 2nd message - bug AMQ-1024
|
||||
// producer.send(msg);
|
||||
Thread.sleep(100);
|
||||
|
||||
// Verify exclusive consumer receives the message.
|
||||
assertNotNull(exclusiveConsumer.receive(100));
|
||||
assertNull(fallbackConsumer.receive(100));
|
||||
|
||||
} finally {
|
||||
fallbackSession.close();
|
||||
senderSession.close();
|
||||
conn.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testExclusiveConsumerSelectedCreatedAfter() throws JMSException, InterruptedException {
|
||||
Connection conn = createConnection(true);
|
||||
|
||||
Session exclusiveSession = null;
|
||||
Session fallbackSession = null;
|
||||
Session senderSession = null;
|
||||
|
||||
try {
|
||||
|
||||
exclusiveSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
fallbackSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
senderSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
ActiveMQQueue fallbackQueue = new ActiveMQQueue("TEST.QUEUE5");
|
||||
MessageConsumer fallbackConsumer = fallbackSession.createConsumer(fallbackQueue);
|
||||
|
||||
ActiveMQQueue exclusiveQueue = new ActiveMQQueue("TEST.QUEUE5?consumer.exclusive=true");
|
||||
MessageConsumer exclusiveConsumer = exclusiveSession.createConsumer(exclusiveQueue);
|
||||
|
||||
ActiveMQQueue senderQueue = new ActiveMQQueue("TEST.QUEUE5");
|
||||
|
||||
MessageProducer producer = senderSession.createProducer(senderQueue);
|
||||
|
||||
Message msg = senderSession.createTextMessage("test");
|
||||
producer.send(msg);
|
||||
Thread.sleep(100);
|
||||
|
||||
// Verify exclusive consumer receives the message.
|
||||
assertNotNull(exclusiveConsumer.receive(100));
|
||||
assertNull(fallbackConsumer.receive(100));
|
||||
|
||||
} finally {
|
||||
fallbackSession.close();
|
||||
senderSession.close();
|
||||
conn.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testFailoverToAnotherExclusiveConsumerCreatedFirst() throws JMSException,
|
||||
InterruptedException {
|
||||
Connection conn = createConnection(true);
|
||||
|
||||
Session exclusiveSession1 = null;
|
||||
Session exclusiveSession2 = null;
|
||||
Session fallbackSession = null;
|
||||
Session senderSession = null;
|
||||
|
||||
try {
|
||||
|
||||
exclusiveSession1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
exclusiveSession2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
fallbackSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
senderSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
// This creates the exclusive consumer first which avoids AMQ-1024
|
||||
// bug.
|
||||
ActiveMQQueue exclusiveQueue = new ActiveMQQueue("TEST.QUEUE2?consumer.exclusive=true");
|
||||
MessageConsumer exclusiveConsumer1 = exclusiveSession1.createConsumer(exclusiveQueue);
|
||||
MessageConsumer exclusiveConsumer2 = exclusiveSession2.createConsumer(exclusiveQueue);
|
||||
|
||||
ActiveMQQueue fallbackQueue = new ActiveMQQueue("TEST.QUEUE2");
|
||||
MessageConsumer fallbackConsumer = fallbackSession.createConsumer(fallbackQueue);
|
||||
|
||||
ActiveMQQueue senderQueue = new ActiveMQQueue("TEST.QUEUE2");
|
||||
|
||||
MessageProducer producer = senderSession.createProducer(senderQueue);
|
||||
|
||||
Message msg = senderSession.createTextMessage("test");
|
||||
producer.send(msg);
|
||||
Thread.sleep(100);
|
||||
|
||||
// Verify exclusive consumer receives the message.
|
||||
assertNotNull(exclusiveConsumer1.receive(100));
|
||||
assertNull(exclusiveConsumer2.receive(100));
|
||||
assertNull(fallbackConsumer.receive(100));
|
||||
|
||||
// Close the exclusive consumer to verify the non-exclusive consumer
|
||||
// takes over
|
||||
exclusiveConsumer1.close();
|
||||
|
||||
producer.send(msg);
|
||||
producer.send(msg);
|
||||
|
||||
assertNotNull(exclusiveConsumer2.receive(100));
|
||||
assertNull(fallbackConsumer.receive(100));
|
||||
|
||||
} finally {
|
||||
fallbackSession.close();
|
||||
senderSession.close();
|
||||
conn.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testFailoverToAnotherExclusiveConsumerCreatedAfter() throws JMSException,
|
||||
InterruptedException {
|
||||
Connection conn = createConnection(true);
|
||||
|
||||
Session exclusiveSession1 = null;
|
||||
Session exclusiveSession2 = null;
|
||||
Session fallbackSession = null;
|
||||
Session senderSession = null;
|
||||
|
||||
try {
|
||||
|
||||
exclusiveSession1 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
exclusiveSession2 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
fallbackSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
senderSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
// This creates the exclusive consumer first which avoids AMQ-1024
|
||||
// bug.
|
||||
ActiveMQQueue exclusiveQueue = new ActiveMQQueue("TEST.QUEUE6?consumer.exclusive=true");
|
||||
MessageConsumer exclusiveConsumer1 = exclusiveSession1.createConsumer(exclusiveQueue);
|
||||
|
||||
ActiveMQQueue fallbackQueue = new ActiveMQQueue("TEST.QUEUE6");
|
||||
MessageConsumer fallbackConsumer = fallbackSession.createConsumer(fallbackQueue);
|
||||
|
||||
MessageConsumer exclusiveConsumer2 = exclusiveSession2.createConsumer(exclusiveQueue);
|
||||
|
||||
ActiveMQQueue senderQueue = new ActiveMQQueue("TEST.QUEUE6");
|
||||
|
||||
MessageProducer producer = senderSession.createProducer(senderQueue);
|
||||
|
||||
Message msg = senderSession.createTextMessage("test");
|
||||
producer.send(msg);
|
||||
Thread.sleep(100);
|
||||
|
||||
// Verify exclusive consumer receives the message.
|
||||
assertNotNull(exclusiveConsumer1.receive(100));
|
||||
assertNull(exclusiveConsumer2.receive(100));
|
||||
assertNull(fallbackConsumer.receive(100));
|
||||
|
||||
// Close the exclusive consumer to verify the non-exclusive consumer
|
||||
// takes over
|
||||
exclusiveConsumer1.close();
|
||||
|
||||
producer.send(msg);
|
||||
producer.send(msg);
|
||||
|
||||
assertNotNull(exclusiveConsumer2.receive(1000));
|
||||
assertNull(fallbackConsumer.receive(100));
|
||||
|
||||
} finally {
|
||||
fallbackSession.close();
|
||||
senderSession.close();
|
||||
conn.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testFailoverToNonExclusiveConsumer() throws JMSException, InterruptedException {
|
||||
Connection conn = createConnection(true);
|
||||
|
||||
Session exclusiveSession = null;
|
||||
Session fallbackSession = null;
|
||||
Session senderSession = null;
|
||||
|
||||
try {
|
||||
|
||||
exclusiveSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
fallbackSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
senderSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
// This creates the exclusive consumer first which avoids AMQ-1024
|
||||
// bug.
|
||||
ActiveMQQueue exclusiveQueue = new ActiveMQQueue("TEST.QUEUE3?consumer.exclusive=true");
|
||||
MessageConsumer exclusiveConsumer = exclusiveSession.createConsumer(exclusiveQueue);
|
||||
|
||||
ActiveMQQueue fallbackQueue = new ActiveMQQueue("TEST.QUEUE3");
|
||||
MessageConsumer fallbackConsumer = fallbackSession.createConsumer(fallbackQueue);
|
||||
|
||||
ActiveMQQueue senderQueue = new ActiveMQQueue("TEST.QUEUE3");
|
||||
|
||||
MessageProducer producer = senderSession.createProducer(senderQueue);
|
||||
|
||||
Message msg = senderSession.createTextMessage("test");
|
||||
producer.send(msg);
|
||||
Thread.sleep(100);
|
||||
|
||||
// Verify exclusive consumer receives the message.
|
||||
assertNotNull(exclusiveConsumer.receive(100));
|
||||
assertNull(fallbackConsumer.receive(100));
|
||||
|
||||
// Close the exclusive consumer to verify the non-exclusive consumer
|
||||
// takes over
|
||||
exclusiveConsumer.close();
|
||||
|
||||
producer.send(msg);
|
||||
|
||||
assertNotNull(fallbackConsumer.receive(100));
|
||||
|
||||
} finally {
|
||||
fallbackSession.close();
|
||||
senderSession.close();
|
||||
conn.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testFallbackToExclusiveConsumer() throws JMSException, InterruptedException {
|
||||
Connection conn = createConnection(true);
|
||||
|
||||
Session exclusiveSession = null;
|
||||
Session fallbackSession = null;
|
||||
Session senderSession = null;
|
||||
|
||||
try {
|
||||
|
||||
exclusiveSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
fallbackSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
senderSession = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
// This creates the exclusive consumer first which avoids AMQ-1024
|
||||
// bug.
|
||||
ActiveMQQueue exclusiveQueue = new ActiveMQQueue("TEST.QUEUE4?consumer.exclusive=true");
|
||||
MessageConsumer exclusiveConsumer = exclusiveSession.createConsumer(exclusiveQueue);
|
||||
|
||||
ActiveMQQueue fallbackQueue = new ActiveMQQueue("TEST.QUEUE4");
|
||||
MessageConsumer fallbackConsumer = fallbackSession.createConsumer(fallbackQueue);
|
||||
|
||||
ActiveMQQueue senderQueue = new ActiveMQQueue("TEST.QUEUE4");
|
||||
|
||||
MessageProducer producer = senderSession.createProducer(senderQueue);
|
||||
|
||||
Message msg = senderSession.createTextMessage("test");
|
||||
producer.send(msg);
|
||||
Thread.sleep(100);
|
||||
|
||||
// Verify exclusive consumer receives the message.
|
||||
assertNotNull(exclusiveConsumer.receive(100));
|
||||
assertNull(fallbackConsumer.receive(100));
|
||||
|
||||
// Close the exclusive consumer to verify the non-exclusive consumer
|
||||
// takes over
|
||||
exclusiveConsumer.close();
|
||||
|
||||
producer.send(msg);
|
||||
|
||||
// Verify other non-exclusive consumer receices the message.
|
||||
assertNotNull(fallbackConsumer.receive(100));
|
||||
|
||||
// Create exclusive consumer to determine if it will start receiving
|
||||
// the messages.
|
||||
exclusiveConsumer = exclusiveSession.createConsumer(exclusiveQueue);
|
||||
|
||||
producer.send(msg);
|
||||
assertNotNull(exclusiveConsumer.receive(100));
|
||||
assertNull(fallbackConsumer.receive(100));
|
||||
|
||||
} finally {
|
||||
fallbackSession.close();
|
||||
senderSession.close();
|
||||
conn.close();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* 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.concurrent.TimeUnit;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
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.store.kahadb.KahaDBPersistenceAdapter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* User: gtully
|
||||
*/
|
||||
@RunWith(BlockJUnit4ClassRunner.class)
|
||||
public class ExpiryHogTest extends JmsMultipleClientsTestSupport {
|
||||
boolean sleep = false;
|
||||
|
||||
int numMessages = 4;
|
||||
|
||||
@Test(timeout = 2 * 60 * 1000)
|
||||
public void testImmediateDispatchWhenCacheDisabled() throws Exception {
|
||||
ConnectionFactory f = createConnectionFactory();
|
||||
destination = createDestination();
|
||||
startConsumers(f, destination);
|
||||
sleep = true;
|
||||
this.startProducers(f, destination, numMessages);
|
||||
allMessagesList.assertMessagesReceived(numMessages);
|
||||
}
|
||||
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService bs = new BrokerService();
|
||||
bs.setDeleteAllMessagesOnStartup(true);
|
||||
PolicyMap policyMap = new PolicyMap();
|
||||
PolicyEntry defaultEntry = new PolicyEntry();
|
||||
defaultEntry.setExpireMessagesPeriod(5000);
|
||||
defaultEntry.setUseCache(false);
|
||||
policyMap.setDefaultEntry(defaultEntry);
|
||||
bs.setDestinationPolicy(policyMap);
|
||||
|
||||
KahaDBPersistenceAdapter ad = (KahaDBPersistenceAdapter) bs.getPersistenceAdapter();
|
||||
ad.setConcurrentStoreAndDispatchQueues(true);
|
||||
return bs;
|
||||
}
|
||||
|
||||
protected TextMessage createTextMessage(Session session, String initText) throws Exception {
|
||||
if (sleep) {
|
||||
TimeUnit.SECONDS.sleep(10);
|
||||
}
|
||||
TextMessage msg = super.createTextMessage(session, initText);
|
||||
msg.setJMSExpiration(4000);
|
||||
return msg;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
autoFail = false;
|
||||
persistent = true;
|
||||
super.setUp();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,937 @@
|
|||
/**
|
||||
* 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.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.jms.Topic;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.broker.jmx.DestinationViewMBean;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Test cases used to test the JMS message consumer.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JMSConsumerTest extends JmsTestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JMSConsumerTest.class);
|
||||
|
||||
public ActiveMQDestination destination;
|
||||
public int deliveryMode;
|
||||
public int prefetch;
|
||||
public int ackMode;
|
||||
public byte destinationType;
|
||||
public boolean durableConsumer;
|
||||
|
||||
public static Test suite() {
|
||||
return suite(JMSConsumerTest.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(suite());
|
||||
}
|
||||
|
||||
public void initCombosForTestMessageListenerWithConsumerCanBeStopped() {
|
||||
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 testMessageListenerWithConsumerCanBeStopped() throws Exception {
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
final CountDownLatch done1 = new CountDownLatch(1);
|
||||
final CountDownLatch done2 = new CountDownLatch(1);
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
ActiveMQMessageConsumer consumer = (ActiveMQMessageConsumer)session.createConsumer(destination);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message m) {
|
||||
counter.incrementAndGet();
|
||||
if (counter.get() == 1) {
|
||||
done1.countDown();
|
||||
}
|
||||
if (counter.get() == 2) {
|
||||
done2.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Send a first message to make sure that the consumer dispatcher is
|
||||
// running
|
||||
sendMessages(session, destination, 1);
|
||||
assertTrue(done1.await(1, TimeUnit.SECONDS));
|
||||
assertEquals(1, counter.get());
|
||||
|
||||
// Stop the consumer.
|
||||
consumer.stop();
|
||||
|
||||
// Send a message, but should not get delivered.
|
||||
sendMessages(session, destination, 1);
|
||||
assertFalse(done2.await(1, TimeUnit.SECONDS));
|
||||
assertEquals(1, counter.get());
|
||||
|
||||
// Start the consumer, and the message should now get delivered.
|
||||
consumer.start();
|
||||
assertTrue(done2.await(1, TimeUnit.SECONDS));
|
||||
assertEquals(2, counter.get());
|
||||
}
|
||||
|
||||
|
||||
public void testMessageListenerWithConsumerCanBeStoppedConcurently() throws Exception {
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
final CountDownLatch closeDone = new CountDownLatch(1);
|
||||
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
destination = createDestination(session, ActiveMQDestination.QUEUE_TYPE);
|
||||
|
||||
// preload the queue
|
||||
sendMessages(session, destination, 2000);
|
||||
|
||||
|
||||
final ActiveMQMessageConsumer consumer = (ActiveMQMessageConsumer)session.createConsumer(destination);
|
||||
|
||||
final Map<Thread, Throwable> exceptions =
|
||||
Collections.synchronizedMap(new HashMap<Thread, Throwable>());
|
||||
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
LOG.error("Uncaught exception:", e);
|
||||
exceptions.put(t, e);
|
||||
}
|
||||
});
|
||||
|
||||
final class AckAndClose implements Runnable {
|
||||
private final Message message;
|
||||
|
||||
public AckAndClose(Message m) {
|
||||
this.message = m;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
int count = counter.incrementAndGet();
|
||||
if (count == 590) {
|
||||
// close in a separate thread is ok by jms
|
||||
consumer.close();
|
||||
closeDone.countDown();
|
||||
}
|
||||
if (count % 200 == 0) {
|
||||
// ensure there are some outstanding messages
|
||||
// ack every 200
|
||||
message.acknowledge();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Exception on close or ack:", e);
|
||||
exceptions.put(Thread.currentThread(), e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
final ExecutorService executor = Executors.newCachedThreadPool();
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message m) {
|
||||
// ack and close eventually in separate thread
|
||||
executor.execute(new AckAndClose(m));
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(closeDone.await(20, TimeUnit.SECONDS));
|
||||
// await possible exceptions
|
||||
Thread.sleep(1000);
|
||||
assertTrue("no exceptions: " + exceptions, exceptions.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
public void initCombosForTestMutiReceiveWithPrefetch1() {
|
||||
addCombinationValues("deliveryMode", new Object[] {Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
||||
addCombinationValues("ackMode", new Object[] {Integer.valueOf(Session.AUTO_ACKNOWLEDGE), Integer.valueOf(Session.DUPS_OK_ACKNOWLEDGE),
|
||||
Integer.valueOf(Session.CLIENT_ACKNOWLEDGE)});
|
||||
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 testMutiReceiveWithPrefetch1() throws Exception {
|
||||
|
||||
// Set prefetch to 1
|
||||
connection.getPrefetchPolicy().setAll(1);
|
||||
connection.start();
|
||||
|
||||
// Use all the ack modes
|
||||
Session session = connection.createSession(false, ackMode);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
|
||||
// Send the messages
|
||||
sendMessages(session, destination, 4);
|
||||
|
||||
// Make sure 4 messages were delivered.
|
||||
Message message = null;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
message = consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
}
|
||||
assertNull(consumer.receiveNoWait());
|
||||
message.acknowledge();
|
||||
}
|
||||
|
||||
public void initCombosForTestDurableConsumerSelectorChange() {
|
||||
addCombinationValues("deliveryMode", new Object[] {Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
||||
addCombinationValues("destinationType", new Object[] {Byte.valueOf(ActiveMQDestination.TOPIC_TYPE)});
|
||||
}
|
||||
|
||||
public void testDurableConsumerSelectorChange() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.setClientID("test");
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setDeliveryMode(deliveryMode);
|
||||
MessageConsumer consumer = session.createDurableSubscriber((Topic)destination, "test", "color='red'", false);
|
||||
|
||||
// Send the messages
|
||||
TextMessage message = session.createTextMessage("1st");
|
||||
message.setStringProperty("color", "red");
|
||||
producer.send(message);
|
||||
|
||||
Message m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
assertEquals("1st", ((TextMessage)m).getText());
|
||||
|
||||
// Change the subscription.
|
||||
consumer.close();
|
||||
consumer = session.createDurableSubscriber((Topic)destination, "test", "color='blue'", false);
|
||||
|
||||
message = session.createTextMessage("2nd");
|
||||
message.setStringProperty("color", "red");
|
||||
producer.send(message);
|
||||
message = session.createTextMessage("3rd");
|
||||
message.setStringProperty("color", "blue");
|
||||
producer.send(message);
|
||||
|
||||
// Selector should skip the 2nd message.
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
assertEquals("3rd", ((TextMessage)m).getText());
|
||||
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void initCombosForTestSendReceiveBytesMessage() {
|
||||
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 testSendReceiveBytesMessage() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
|
||||
BytesMessage message = session.createBytesMessage();
|
||||
message.writeBoolean(true);
|
||||
message.writeBoolean(false);
|
||||
producer.send(message);
|
||||
|
||||
// Make sure only 1 message was delivered.
|
||||
BytesMessage m = (BytesMessage)consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
assertTrue(m.readBoolean());
|
||||
assertFalse(m.readBoolean());
|
||||
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void initCombosForTestSetMessageListenerAfterStart() {
|
||||
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 testSetMessageListenerAfterStart() throws Exception {
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
final CountDownLatch done = new CountDownLatch(1);
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
|
||||
// Send the messages
|
||||
sendMessages(session, destination, 4);
|
||||
|
||||
// See if the message get sent to the listener
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message m) {
|
||||
counter.incrementAndGet();
|
||||
if (counter.get() == 4) {
|
||||
done.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(done.await(1000, TimeUnit.MILLISECONDS));
|
||||
Thread.sleep(200);
|
||||
|
||||
// Make sure only 4 messages were delivered.
|
||||
assertEquals(4, counter.get());
|
||||
}
|
||||
|
||||
public void initCombosForTestPassMessageListenerIntoCreateConsumer() {
|
||||
addCombinationValues("destinationType", new Object[] {Byte.valueOf(ActiveMQDestination.QUEUE_TYPE), Byte.valueOf(ActiveMQDestination.TOPIC_TYPE)});
|
||||
}
|
||||
|
||||
public void testPassMessageListenerIntoCreateConsumer() throws Exception {
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
final CountDownLatch done = new CountDownLatch(1);
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
ActiveMQSession session = (ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination, new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message m) {
|
||||
counter.incrementAndGet();
|
||||
if (counter.get() == 4) {
|
||||
done.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
assertNotNull(consumer);
|
||||
|
||||
// Send the messages
|
||||
sendMessages(session, destination, 4);
|
||||
|
||||
assertTrue(done.await(1000, TimeUnit.MILLISECONDS));
|
||||
Thread.sleep(200);
|
||||
|
||||
// Make sure only 4 messages were delivered.
|
||||
assertEquals(4, counter.get());
|
||||
}
|
||||
|
||||
public void initCombosForTestMessageListenerOnMessageCloseUnackedWithPrefetch1StayInQueue() {
|
||||
addCombinationValues("deliveryMode", new Object[] {Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
||||
addCombinationValues("ackMode", new Object[] {Integer.valueOf(Session.CLIENT_ACKNOWLEDGE)});
|
||||
addCombinationValues("destinationType", new Object[] {Byte.valueOf(ActiveMQDestination.QUEUE_TYPE)});
|
||||
}
|
||||
|
||||
public void testMessageListenerOnMessageCloseUnackedWithPrefetch1StayInQueue() throws Exception {
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
final CountDownLatch sendDone = new CountDownLatch(1);
|
||||
final CountDownLatch got2Done = new CountDownLatch(1);
|
||||
|
||||
// Set prefetch to 1
|
||||
connection.getPrefetchPolicy().setAll(1);
|
||||
// This test case does not work if optimized message dispatch is used as
|
||||
// the main thread send block until the consumer receives the
|
||||
// message. This test depends on thread decoupling so that the main
|
||||
// thread can stop the consumer thread.
|
||||
connection.setOptimizedMessageDispatch(false);
|
||||
connection.start();
|
||||
|
||||
// Use all the ack modes
|
||||
Session session = connection.createSession(false, ackMode);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message m) {
|
||||
try {
|
||||
TextMessage tm = (TextMessage)m;
|
||||
LOG.info("Got in first listener: " + tm.getText());
|
||||
assertEquals("" + counter.get(), tm.getText());
|
||||
counter.incrementAndGet();
|
||||
if (counter.get() == 2) {
|
||||
sendDone.await();
|
||||
connection.close();
|
||||
got2Done.countDown();
|
||||
}
|
||||
tm.acknowledge();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Send the messages
|
||||
sendMessages(session, destination, 4);
|
||||
sendDone.countDown();
|
||||
|
||||
// Wait for first 2 messages to arrive.
|
||||
assertTrue(got2Done.await(100000, TimeUnit.MILLISECONDS));
|
||||
|
||||
// Re-start connection.
|
||||
connection = (ActiveMQConnection)factory.createConnection();
|
||||
connections.add(connection);
|
||||
|
||||
connection.getPrefetchPolicy().setAll(1);
|
||||
connection.start();
|
||||
|
||||
// Pickup the remaining messages.
|
||||
final CountDownLatch done2 = new CountDownLatch(1);
|
||||
session = connection.createSession(false, ackMode);
|
||||
consumer = session.createConsumer(destination);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message m) {
|
||||
try {
|
||||
TextMessage tm = (TextMessage)m;
|
||||
LOG.info("Got in second listener: " + tm.getText());
|
||||
// order is not guaranteed as the connection is started before the listener is set.
|
||||
// assertEquals("" + counter.get(), tm.getText());
|
||||
counter.incrementAndGet();
|
||||
if (counter.get() == 4) {
|
||||
done2.countDown();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
LOG.error("unexpected ex onMessage: ", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(done2.await(1000, TimeUnit.MILLISECONDS));
|
||||
Thread.sleep(200);
|
||||
|
||||
// assert msg 2 was redelivered as close() from onMessages() will only ack in auto_ack and dups_ok mode
|
||||
assertEquals(5, counter.get());
|
||||
}
|
||||
|
||||
public void initCombosForTestMessageListenerAutoAckOnCloseWithPrefetch1() {
|
||||
addCombinationValues("deliveryMode", new Object[] {Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
||||
addCombinationValues("ackMode", new Object[] {Integer.valueOf(Session.AUTO_ACKNOWLEDGE), Integer.valueOf(Session.CLIENT_ACKNOWLEDGE)});
|
||||
addCombinationValues("destinationType", new Object[] {Byte.valueOf(ActiveMQDestination.QUEUE_TYPE)});
|
||||
}
|
||||
|
||||
public void testMessageListenerAutoAckOnCloseWithPrefetch1() throws Exception {
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
final CountDownLatch sendDone = new CountDownLatch(1);
|
||||
final CountDownLatch got2Done = new CountDownLatch(1);
|
||||
|
||||
// Set prefetch to 1
|
||||
connection.getPrefetchPolicy().setAll(1);
|
||||
// This test case does not work if optimized message dispatch is used as
|
||||
// the main thread send block until the consumer receives the
|
||||
// message. This test depends on thread decoupling so that the main
|
||||
// thread can stop the consumer thread.
|
||||
connection.setOptimizedMessageDispatch(false);
|
||||
connection.start();
|
||||
|
||||
// Use all the ack modes
|
||||
Session session = connection.createSession(false, ackMode);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message m) {
|
||||
try {
|
||||
TextMessage tm = (TextMessage)m;
|
||||
LOG.info("Got in first listener: " + tm.getText());
|
||||
assertEquals("" + counter.get(), tm.getText());
|
||||
counter.incrementAndGet();
|
||||
m.acknowledge();
|
||||
if (counter.get() == 2) {
|
||||
sendDone.await();
|
||||
connection.close();
|
||||
got2Done.countDown();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Send the messages
|
||||
sendMessages(session, destination, 4);
|
||||
sendDone.countDown();
|
||||
|
||||
// Wait for first 2 messages to arrive.
|
||||
assertTrue(got2Done.await(100000, TimeUnit.MILLISECONDS));
|
||||
|
||||
// Re-start connection.
|
||||
connection = (ActiveMQConnection)factory.createConnection();
|
||||
connections.add(connection);
|
||||
|
||||
connection.getPrefetchPolicy().setAll(1);
|
||||
connection.start();
|
||||
|
||||
// Pickup the remaining messages.
|
||||
final CountDownLatch done2 = new CountDownLatch(1);
|
||||
session = connection.createSession(false, ackMode);
|
||||
consumer = session.createConsumer(destination);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message m) {
|
||||
try {
|
||||
TextMessage tm = (TextMessage)m;
|
||||
LOG.info("Got in second listener: " + tm.getText());
|
||||
counter.incrementAndGet();
|
||||
if (counter.get() == 4) {
|
||||
done2.countDown();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
LOG.error("unexpected ex onMessage: ", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(done2.await(1000, TimeUnit.MILLISECONDS));
|
||||
Thread.sleep(200);
|
||||
|
||||
// close from onMessage with Auto_ack will ack
|
||||
// Make sure only 4 messages were delivered.
|
||||
assertEquals(4, counter.get());
|
||||
}
|
||||
|
||||
public void initCombosForTestMessageListenerWithConsumerWithPrefetch1() {
|
||||
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 testMessageListenerWithConsumerWithPrefetch1() throws Exception {
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
final CountDownLatch done = new CountDownLatch(1);
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.getPrefetchPolicy().setAll(1);
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message m) {
|
||||
counter.incrementAndGet();
|
||||
if (counter.get() == 4) {
|
||||
done.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Send the messages
|
||||
sendMessages(session, destination, 4);
|
||||
|
||||
assertTrue(done.await(1000, TimeUnit.MILLISECONDS));
|
||||
Thread.sleep(200);
|
||||
|
||||
// Make sure only 4 messages were delivered.
|
||||
assertEquals(4, counter.get());
|
||||
}
|
||||
|
||||
public void initCombosForTestMessageListenerWithConsumer() {
|
||||
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 testMessageListenerWithConsumer() throws Exception {
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
final CountDownLatch done = new CountDownLatch(1);
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message m) {
|
||||
counter.incrementAndGet();
|
||||
if (counter.get() == 4) {
|
||||
done.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Send the messages
|
||||
sendMessages(session, destination, 4);
|
||||
|
||||
assertTrue(done.await(1000, TimeUnit.MILLISECONDS));
|
||||
Thread.sleep(200);
|
||||
|
||||
// Make sure only 4 messages were delivered.
|
||||
assertEquals(4, counter.get());
|
||||
}
|
||||
|
||||
public void initCombosForTestUnackedWithPrefetch1StayInQueue() {
|
||||
addCombinationValues("deliveryMode", new Object[] {Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
||||
addCombinationValues("ackMode", new Object[] {Integer.valueOf(Session.AUTO_ACKNOWLEDGE), Integer.valueOf(Session.DUPS_OK_ACKNOWLEDGE),
|
||||
Integer.valueOf(Session.CLIENT_ACKNOWLEDGE)});
|
||||
addCombinationValues("destinationType", new Object[] {Byte.valueOf(ActiveMQDestination.QUEUE_TYPE)});
|
||||
}
|
||||
|
||||
public void testUnackedWithPrefetch1StayInQueue() throws Exception {
|
||||
|
||||
// Set prefetch to 1
|
||||
connection.getPrefetchPolicy().setAll(1);
|
||||
connection.start();
|
||||
|
||||
// Use all the ack modes
|
||||
Session session = connection.createSession(false, ackMode);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
|
||||
// Send the messages
|
||||
sendMessages(session, destination, 4);
|
||||
|
||||
// Only pick up the first 2 messages.
|
||||
Message message = null;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
message = consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
}
|
||||
message.acknowledge();
|
||||
|
||||
connection.close();
|
||||
connection = (ActiveMQConnection)factory.createConnection();
|
||||
connections.add(connection);
|
||||
connection.getPrefetchPolicy().setAll(1);
|
||||
connection.start();
|
||||
|
||||
// Use all the ack modes
|
||||
session = connection.createSession(false, ackMode);
|
||||
consumer = session.createConsumer(destination);
|
||||
|
||||
// Pickup the rest of the messages.
|
||||
for (int i = 0; i < 2; i++) {
|
||||
message = consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
}
|
||||
message.acknowledge();
|
||||
assertNull(consumer.receiveNoWait());
|
||||
|
||||
}
|
||||
|
||||
public void initCombosForTestPrefetch1MessageNotDispatched() {
|
||||
addCombinationValues("deliveryMode", new Object[] {Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
||||
}
|
||||
|
||||
public void testPrefetch1MessageNotDispatched() throws Exception {
|
||||
|
||||
// Set prefetch to 1
|
||||
connection.getPrefetchPolicy().setAll(1);
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(true, 0);
|
||||
destination = new ActiveMQQueue("TEST");
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
|
||||
// Send 2 messages to the destination.
|
||||
sendMessages(session, destination, 2);
|
||||
session.commit();
|
||||
|
||||
// The prefetch should fill up with 1 message.
|
||||
// Since prefetch is still full, the 2nd message should get dispatched
|
||||
// to another consumer.. lets create the 2nd consumer test that it does
|
||||
// make sure it does.
|
||||
ActiveMQConnection connection2 = (ActiveMQConnection)factory.createConnection();
|
||||
connection2.start();
|
||||
connections.add(connection2);
|
||||
Session session2 = connection2.createSession(true, 0);
|
||||
MessageConsumer consumer2 = session2.createConsumer(destination);
|
||||
|
||||
// Pick up the first message.
|
||||
Message message1 = consumer.receive(1000);
|
||||
assertNotNull(message1);
|
||||
|
||||
// Pick up the 2nd messages.
|
||||
Message message2 = consumer2.receive(5000);
|
||||
assertNotNull(message2);
|
||||
|
||||
session.commit();
|
||||
session2.commit();
|
||||
|
||||
assertNull(consumer.receiveNoWait());
|
||||
|
||||
}
|
||||
|
||||
public void initCombosForTestDontStart() {
|
||||
addCombinationValues("deliveryMode", new Object[] {Integer.valueOf(DeliveryMode.NON_PERSISTENT)});
|
||||
addCombinationValues("destinationType", new Object[] {Byte.valueOf(ActiveMQDestination.QUEUE_TYPE), Byte.valueOf(ActiveMQDestination.TOPIC_TYPE)});
|
||||
}
|
||||
|
||||
public void testDontStart() throws Exception {
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
|
||||
// Send the messages
|
||||
sendMessages(session, destination, 1);
|
||||
|
||||
// Make sure no messages were delivered.
|
||||
assertNull(consumer.receive(1000));
|
||||
}
|
||||
|
||||
public void initCombosForTestStartAfterSend() {
|
||||
addCombinationValues("deliveryMode", new Object[] {Integer.valueOf(DeliveryMode.NON_PERSISTENT)});
|
||||
addCombinationValues("destinationType", new Object[] {Byte.valueOf(ActiveMQDestination.QUEUE_TYPE), Byte.valueOf(ActiveMQDestination.TOPIC_TYPE)});
|
||||
}
|
||||
|
||||
public void testStartAfterSend() throws Exception {
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
|
||||
// Send the messages
|
||||
sendMessages(session, destination, 1);
|
||||
|
||||
// Start the conncection after the message was sent.
|
||||
connection.start();
|
||||
|
||||
// Make sure only 1 message was delivered.
|
||||
assertNotNull(consumer.receive(1000));
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void initCombosForTestReceiveMessageWithConsumer() {
|
||||
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 testReceiveMessageWithConsumer() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
|
||||
// Send the messages
|
||||
sendMessages(session, destination, 1);
|
||||
|
||||
// Make sure only 1 message was delivered.
|
||||
Message m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
assertEquals("0", ((TextMessage)m).getText());
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
|
||||
public void testDupsOkConsumer() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
|
||||
destination = createDestination(session, ActiveMQDestination.QUEUE_TYPE);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
|
||||
// Send the messages
|
||||
sendMessages(session, destination, 4);
|
||||
|
||||
// Make sure only 4 message are delivered.
|
||||
for( int i=0; i < 4; i++){
|
||||
Message m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
}
|
||||
assertNull(consumer.receive(1000));
|
||||
|
||||
// Close out the consumer.. no other messages should be left on the queue.
|
||||
consumer.close();
|
||||
|
||||
consumer = session.createConsumer(destination);
|
||||
assertNull(consumer.receive(1000));
|
||||
}
|
||||
|
||||
public void testRedispatchOfUncommittedTx() throws Exception {
|
||||
|
||||
connection.start();
|
||||
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
destination = createDestination(session, ActiveMQDestination.QUEUE_TYPE);
|
||||
|
||||
sendMessages(connection, destination, 2);
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
assertNotNull(consumer.receive(1000));
|
||||
assertNotNull(consumer.receive(1000));
|
||||
|
||||
// install another consumer while message dispatch is unacked/uncommitted
|
||||
Session redispatchSession = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
MessageConsumer redispatchConsumer = redispatchSession.createConsumer(destination);
|
||||
|
||||
// no commit so will auto rollback and get re-dispatched to redisptachConsumer
|
||||
session.close();
|
||||
|
||||
Message msg = redispatchConsumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertTrue("redelivered flag set", msg.getJMSRedelivered());
|
||||
assertEquals(2, msg.getLongProperty("JMSXDeliveryCount"));
|
||||
|
||||
msg = redispatchConsumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertTrue(msg.getJMSRedelivered());
|
||||
assertEquals(2, msg.getLongProperty("JMSXDeliveryCount"));
|
||||
redispatchSession.commit();
|
||||
|
||||
assertNull(redispatchConsumer.receive(500));
|
||||
redispatchSession.close();
|
||||
}
|
||||
|
||||
|
||||
public void testRedispatchOfRolledbackTx() throws Exception {
|
||||
|
||||
connection.start();
|
||||
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
destination = createDestination(session, ActiveMQDestination.QUEUE_TYPE);
|
||||
|
||||
sendMessages(connection, destination, 2);
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
assertNotNull(consumer.receive(1000));
|
||||
assertNotNull(consumer.receive(1000));
|
||||
|
||||
// install another consumer while message dispatch is unacked/uncommitted
|
||||
Session redispatchSession = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
MessageConsumer redispatchConsumer = redispatchSession.createConsumer(destination);
|
||||
|
||||
session.rollback();
|
||||
session.close();
|
||||
|
||||
Message msg = redispatchConsumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertTrue(msg.getJMSRedelivered());
|
||||
assertEquals(2, msg.getLongProperty("JMSXDeliveryCount"));
|
||||
msg = redispatchConsumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertTrue(msg.getJMSRedelivered());
|
||||
assertEquals(2, msg.getLongProperty("JMSXDeliveryCount"));
|
||||
redispatchSession.commit();
|
||||
|
||||
assertNull(redispatchConsumer.receive(500));
|
||||
redispatchSession.close();
|
||||
}
|
||||
|
||||
|
||||
public void initCombosForTestAckOfExpired() {
|
||||
addCombinationValues("destinationType",
|
||||
new Object[] {Byte.valueOf(ActiveMQDestination.QUEUE_TYPE), Byte.valueOf(ActiveMQDestination.TOPIC_TYPE)});
|
||||
}
|
||||
|
||||
public void testAckOfExpired() throws Exception {
|
||||
|
||||
ActiveMQConnectionFactory fact = new ActiveMQConnectionFactory("vm://localhost?jms.prefetchPolicy.all=4&jms.sendAcksAsync=false");
|
||||
connection = fact.createActiveMQConnection();
|
||||
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = (ActiveMQDestination) (destinationType == ActiveMQDestination.QUEUE_TYPE ?
|
||||
session.createQueue("test") : session.createTopic("test"));
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
connection.setStatsEnabled(true);
|
||||
|
||||
Session sendSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = sendSession.createProducer(destination);
|
||||
producer.setTimeToLive(1000);
|
||||
final int count = 4;
|
||||
for (int i = 0; i < count; i++) {
|
||||
TextMessage message = sendSession.createTextMessage("" + i);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
// let first bunch in queue expire
|
||||
Thread.sleep(2000);
|
||||
|
||||
producer.setTimeToLive(0);
|
||||
for (int i = 0; i < count; i++) {
|
||||
TextMessage message = sendSession.createTextMessage("no expiry" + i);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
ActiveMQMessageConsumer amqConsumer = (ActiveMQMessageConsumer) consumer;
|
||||
|
||||
for(int i=0; i<count; i++) {
|
||||
TextMessage msg = (TextMessage) amqConsumer.receive();
|
||||
assertNotNull(msg);
|
||||
assertTrue("message has \"no expiry\" text: " + msg.getText(), msg.getText().contains("no expiry"));
|
||||
|
||||
// force an ack when there are expired messages
|
||||
amqConsumer.acknowledge();
|
||||
}
|
||||
assertEquals("consumer has expiredMessages", count, amqConsumer.getConsumerStats().getExpiredMessageCount().getCount());
|
||||
|
||||
DestinationViewMBean view = createView(destination);
|
||||
|
||||
assertEquals("Wrong inFlightCount: " + view.getInFlightCount(), 0, view.getInFlightCount());
|
||||
assertEquals("Wrong dispatch count: " + view.getDispatchCount(), 8, view.getDispatchCount());
|
||||
assertEquals("Wrong dequeue count: " + view.getDequeueCount(), 8, view.getDequeueCount());
|
||||
assertEquals("Wrong expired count: " + view.getExpiredCount(), 4, view.getExpiredCount());
|
||||
}
|
||||
|
||||
protected DestinationViewMBean createView(ActiveMQDestination destination) throws Exception {
|
||||
|
||||
String domain = "org.apache.activemq";
|
||||
ObjectName name;
|
||||
if (destination.isQueue()) {
|
||||
name = new ObjectName(domain + ":type=Broker,brokerName=localhost,destinationType=Queue,destinationName=test");
|
||||
} else {
|
||||
name = new ObjectName(domain + ":type=Broker,brokerName=localhost,destinationType=Topic,destinationName=test");
|
||||
}
|
||||
return (DestinationViewMBean)broker.getManagementContext().newProxyInstance(name, DestinationViewMBean.class, true);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* 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.Message;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JMSDurableTopicRedeliverTest extends JmsTopicRedeliverTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JMSDurableTopicRedeliverTest.class);
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
durable = true;
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends and consumes the messages.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testRedeliverNewSession() throws Exception {
|
||||
String text = "TEST: " + System.currentTimeMillis();
|
||||
Message sendMessage = session.createTextMessage(text);
|
||||
|
||||
if (verbose) {
|
||||
LOG.info("About to send a message: " + sendMessage + " with text: " + text);
|
||||
}
|
||||
producer.send(producerDestination, sendMessage);
|
||||
|
||||
// receive but don't acknowledge
|
||||
Message unackMessage = consumer.receive(1000);
|
||||
assertNotNull(unackMessage);
|
||||
String unackId = unackMessage.getJMSMessageID();
|
||||
assertEquals(((TextMessage)unackMessage).getText(), text);
|
||||
assertFalse(unackMessage.getJMSRedelivered());
|
||||
assertEquals(unackMessage.getIntProperty("JMSXDeliveryCount"), 1);
|
||||
consumeSession.close();
|
||||
consumer.close();
|
||||
|
||||
// receive then acknowledge
|
||||
consumeSession = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
consumer = createConsumer();
|
||||
Message ackMessage = consumer.receive(1000);
|
||||
assertNotNull(ackMessage);
|
||||
ackMessage.acknowledge();
|
||||
String ackId = ackMessage.getJMSMessageID();
|
||||
assertEquals(((TextMessage)ackMessage).getText(), text);
|
||||
assertTrue(ackMessage.getJMSRedelivered());
|
||||
assertEquals(ackMessage.getIntProperty("JMSXDeliveryCount"), 2);
|
||||
assertEquals(unackId, ackId);
|
||||
consumeSession.close();
|
||||
consumer.close();
|
||||
|
||||
consumeSession = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
consumer = createConsumer();
|
||||
assertNull(consumer.receive(1000));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
/**
|
||||
* 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.DeliveryMode;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.Test;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
|
||||
/**
|
||||
* Test cases used to test the JMS message exclusive consumers.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JMSExclusiveConsumerTest extends JmsTestSupport {
|
||||
|
||||
public int deliveryMode;
|
||||
|
||||
public static Test suite() {
|
||||
return suite(JMSExclusiveConsumerTest.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(suite());
|
||||
}
|
||||
|
||||
public void initCombosForTestRoundRobinDispatchOnNonExclusive() {
|
||||
addCombinationValues("deliveryMode", new Object[] {Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows that by default messages are round robined across a set of
|
||||
* consumers.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testRoundRobinDispatchOnNonExclusive() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
ActiveMQQueue destination = new ActiveMQQueue("TEST");
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setDeliveryMode(deliveryMode);
|
||||
|
||||
MessageConsumer consumer1 = session.createConsumer(destination);
|
||||
MessageConsumer consumer2 = session.createConsumer(destination);
|
||||
|
||||
// Send the messages
|
||||
producer.send(session.createTextMessage("1st"));
|
||||
producer.send(session.createTextMessage("2nd"));
|
||||
|
||||
Message m;
|
||||
m = consumer2.receive(1000);
|
||||
assertNotNull(m);
|
||||
|
||||
m = consumer1.receive(1000);
|
||||
assertNotNull(m);
|
||||
|
||||
assertNull(consumer1.receiveNoWait());
|
||||
assertNull(consumer2.receiveNoWait());
|
||||
}
|
||||
|
||||
public void initCombosForTestDispatchExclusive() {
|
||||
addCombinationValues("deliveryMode", new Object[] {Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows that if the "?consumer.exclusive=true" option is added to
|
||||
* destination, then all messages are routed to 1 consumer.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testDispatchExclusive() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
ActiveMQQueue destination = new ActiveMQQueue("TEST?consumer.exclusive=true");
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setDeliveryMode(deliveryMode);
|
||||
|
||||
MessageConsumer consumer1 = session.createConsumer(destination);
|
||||
MessageConsumer consumer2 = session.createConsumer(destination);
|
||||
|
||||
// Send the messages
|
||||
producer.send(session.createTextMessage("1st"));
|
||||
producer.send(session.createTextMessage("2nd"));
|
||||
producer.send(session.createTextMessage("3nd"));
|
||||
|
||||
Message m;
|
||||
m = consumer2.receive(1000);
|
||||
if (m != null) {
|
||||
// Consumer 2 should get all the messages.
|
||||
for (int i = 0; i < 2; i++) {
|
||||
m = consumer2.receive(1000);
|
||||
assertNotNull(m);
|
||||
}
|
||||
} else {
|
||||
// Consumer 1 should get all the messages.
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m = consumer1.receive(1000);
|
||||
assertNotNull(m);
|
||||
}
|
||||
}
|
||||
|
||||
assertNull(consumer1.receiveNoWait());
|
||||
assertNull(consumer2.receiveNoWait());
|
||||
}
|
||||
|
||||
public void testMixExclusiveWithNonExclusive() throws Exception {
|
||||
ActiveMQQueue exclusiveQueue = new ActiveMQQueue("TEST.FOO?consumer.exclusive=true");
|
||||
ActiveMQQueue nonExclusiveQueue = new ActiveMQQueue("TEST.FOO?consumer.exclusive=false");
|
||||
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
MessageConsumer nonExCon = session.createConsumer(nonExclusiveQueue);
|
||||
MessageConsumer exCon = session.createConsumer(exclusiveQueue);
|
||||
|
||||
MessageProducer prod = session.createProducer(exclusiveQueue);
|
||||
prod.send(session.createMessage());
|
||||
prod.send(session.createMessage());
|
||||
prod.send(session.createMessage());
|
||||
|
||||
Message m;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m = exCon.receive(1000);
|
||||
assertNotNull(m);
|
||||
m = nonExCon.receive(1000);
|
||||
assertNull(m);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/**
|
||||
* 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.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;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JMSIndividualAckTest extends TestSupport {
|
||||
|
||||
private Connection connection;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
connection = createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if acknowledged messages are being consumed.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testAckedMessageAreConsumed() throws JMSException {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue(getQueueName());
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.send(session.createTextMessage("Hello"));
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
msg.acknowledge();
|
||||
|
||||
// Reset the session.
|
||||
session.close();
|
||||
session = connection.createSession(false, ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE);
|
||||
|
||||
// Attempt to Consume the message...
|
||||
consumer = session.createConsumer(queue);
|
||||
msg = consumer.receive(1000);
|
||||
assertNull(msg);
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if acknowledged messages are being consumed.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testLastMessageAcked() throws JMSException {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue(getQueueName());
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
TextMessage msg1 = session.createTextMessage("msg1");
|
||||
TextMessage msg2 = session.createTextMessage("msg2");
|
||||
TextMessage msg3 = session.createTextMessage("msg3");
|
||||
producer.send(msg1);
|
||||
producer.send(msg2);
|
||||
producer.send(msg3);
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
msg.acknowledge();
|
||||
|
||||
// Reset the session.
|
||||
session.close();
|
||||
session = connection.createSession(false, ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE);
|
||||
|
||||
// Attempt to Consume the message...
|
||||
consumer = session.createConsumer(queue);
|
||||
msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertEquals(msg1,msg);
|
||||
msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertEquals(msg2,msg);
|
||||
msg = consumer.receive(1000);
|
||||
assertNull(msg);
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if unacknowledged messages are being re-delivered when the consumer connects again.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testUnAckedMessageAreNotConsumedOnSessionClose() throws JMSException {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue(getQueueName());
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.send(session.createTextMessage("Hello"));
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
// Don't ack the message.
|
||||
|
||||
// Reset the session. This should cause the unacknowledged message to be re-delivered.
|
||||
session.close();
|
||||
session = connection.createSession(false, ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE);
|
||||
|
||||
// Attempt to Consume the message...
|
||||
consumer = session.createConsumer(queue);
|
||||
msg = consumer.receive(2000);
|
||||
assertNotNull(msg);
|
||||
msg.acknowledge();
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
protected String getQueueName() {
|
||||
return getClass().getName() + "." + getName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,547 @@
|
|||
/**
|
||||
* 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.net.URISyntaxException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.MapMessage;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageEOFException;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.ObjectMessage;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.StreamMessage;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
|
||||
/**
|
||||
* Test cases used to test the JMS message consumer.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JMSMessageTest extends JmsTestSupport {
|
||||
|
||||
public ActiveMQDestination destination;
|
||||
public int deliveryMode = DeliveryMode.NON_PERSISTENT;
|
||||
public int prefetch;
|
||||
public int ackMode;
|
||||
public byte destinationType = ActiveMQDestination.QUEUE_TYPE;
|
||||
public boolean durableConsumer;
|
||||
public String connectURL = "vm://localhost?marshal=false";
|
||||
|
||||
/**
|
||||
* Run all these tests in both marshaling and non-marshaling mode.
|
||||
*/
|
||||
public void initCombos() {
|
||||
addCombinationValues("connectURL", new Object[] {"vm://localhost?marshal=false",
|
||||
"vm://localhost?marshal=true"});
|
||||
addCombinationValues("deliveryMode", new Object[] {Integer.valueOf(DeliveryMode.NON_PERSISTENT),
|
||||
Integer.valueOf(DeliveryMode.PERSISTENT)});
|
||||
addCombinationValues("destinationType", new Object[] {Byte.valueOf(ActiveMQDestination.QUEUE_TYPE)});
|
||||
}
|
||||
|
||||
public void testTextMessage() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
|
||||
// Send the message.
|
||||
{
|
||||
TextMessage message = session.createTextMessage();
|
||||
message.setText("Hi");
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
// Check the Message
|
||||
{
|
||||
TextMessage message = (TextMessage)consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
assertEquals("Hi", message.getText());
|
||||
}
|
||||
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return suite(JMSMessageTest.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(suite());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionFactory createConnectionFactory() throws URISyntaxException {
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(connectURL);
|
||||
return factory;
|
||||
}
|
||||
|
||||
public void testBytesMessageLength() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
|
||||
// Send the message
|
||||
{
|
||||
BytesMessage message = session.createBytesMessage();
|
||||
message.writeInt(1);
|
||||
message.writeInt(2);
|
||||
message.writeInt(3);
|
||||
message.writeInt(4);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
// Check the message.
|
||||
{
|
||||
BytesMessage message = (BytesMessage)consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
assertEquals(16, message.getBodyLength());
|
||||
}
|
||||
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void testObjectMessage() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
|
||||
// send the message.
|
||||
{
|
||||
ObjectMessage message = session.createObjectMessage();
|
||||
message.setObject("Hi");
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
// Check the message
|
||||
{
|
||||
ObjectMessage message = (ObjectMessage)consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
assertEquals("Hi", message.getObject());
|
||||
}
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void testBytesMessage() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
|
||||
// Send the message
|
||||
{
|
||||
BytesMessage message = session.createBytesMessage();
|
||||
message.writeBoolean(true);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
// Check the message
|
||||
{
|
||||
BytesMessage message = (BytesMessage)consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
assertTrue(message.readBoolean());
|
||||
|
||||
try {
|
||||
message.readByte();
|
||||
fail("Expected exception not thrown.");
|
||||
} catch (MessageEOFException e) {
|
||||
}
|
||||
|
||||
}
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void testStreamMessage() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
|
||||
// Send the message.
|
||||
{
|
||||
StreamMessage message = session.createStreamMessage();
|
||||
message.writeString("This is a test to see how it works.");
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
// Check the message.
|
||||
{
|
||||
StreamMessage message = (StreamMessage)consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
|
||||
// Invalid conversion should throw exception and not move the stream
|
||||
// position.
|
||||
try {
|
||||
message.readByte();
|
||||
fail("Should have received NumberFormatException");
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
|
||||
assertEquals("This is a test to see how it works.", message.readString());
|
||||
|
||||
// Invalid conversion should throw exception and not move the stream
|
||||
// position.
|
||||
try {
|
||||
message.readByte();
|
||||
fail("Should have received MessageEOFException");
|
||||
} catch (MessageEOFException e) {
|
||||
}
|
||||
}
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void testMapMessage() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
|
||||
// send the message.
|
||||
{
|
||||
MapMessage message = session.createMapMessage();
|
||||
message.setBoolean("boolKey", true);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
// get the message.
|
||||
{
|
||||
MapMessage message = (MapMessage)consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
assertTrue(message.getBoolean("boolKey"));
|
||||
}
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
static class ForeignMessage implements TextMessage {
|
||||
|
||||
public int deliveryMode;
|
||||
|
||||
private String messageId;
|
||||
private long timestamp;
|
||||
private String correlationId;
|
||||
private Destination replyTo;
|
||||
private Destination destination;
|
||||
private boolean redelivered;
|
||||
private String type;
|
||||
private long expiration;
|
||||
private int priority;
|
||||
private String text;
|
||||
private final HashMap<String, Object> props = new HashMap<String, Object>();
|
||||
|
||||
@Override
|
||||
public String getJMSMessageID() throws JMSException {
|
||||
return messageId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSMessageID(String arg0) throws JMSException {
|
||||
messageId = arg0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getJMSTimestamp() throws JMSException {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSTimestamp(long arg0) throws JMSException {
|
||||
timestamp = arg0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getJMSCorrelationIDAsBytes() throws JMSException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSCorrelationIDAsBytes(byte[] arg0) throws JMSException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSCorrelationID(String arg0) throws JMSException {
|
||||
correlationId = arg0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJMSCorrelationID() throws JMSException {
|
||||
return correlationId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Destination getJMSReplyTo() throws JMSException {
|
||||
return replyTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSReplyTo(Destination arg0) throws JMSException {
|
||||
replyTo = arg0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Destination getJMSDestination() throws JMSException {
|
||||
return destination;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSDestination(Destination arg0) throws JMSException {
|
||||
destination = arg0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJMSDeliveryMode() throws JMSException {
|
||||
return deliveryMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSDeliveryMode(int arg0) throws JMSException {
|
||||
deliveryMode = arg0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getJMSRedelivered() throws JMSException {
|
||||
return redelivered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSRedelivered(boolean arg0) throws JMSException {
|
||||
redelivered = arg0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJMSType() throws JMSException {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSType(String arg0) throws JMSException {
|
||||
type = arg0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getJMSExpiration() throws JMSException {
|
||||
return expiration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSExpiration(long arg0) throws JMSException {
|
||||
expiration = arg0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJMSPriority() throws JMSException {
|
||||
return priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJMSPriority(int arg0) throws JMSException {
|
||||
priority = arg0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearProperties() throws JMSException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean propertyExists(String arg0) throws JMSException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBooleanProperty(String arg0) throws JMSException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByteProperty(String arg0) throws JMSException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShortProperty(String arg0) throws JMSException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntProperty(String arg0) throws JMSException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongProperty(String arg0) throws JMSException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloatProperty(String arg0) throws JMSException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDoubleProperty(String arg0) throws JMSException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStringProperty(String arg0) throws JMSException {
|
||||
return (String)props.get(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getObjectProperty(String arg0) throws JMSException {
|
||||
return props.get(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<?> getPropertyNames() throws JMSException {
|
||||
return new Vector<String>(props.keySet()).elements();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBooleanProperty(String arg0, boolean arg1) throws JMSException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setByteProperty(String arg0, byte arg1) throws JMSException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShortProperty(String arg0, short arg1) throws JMSException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIntProperty(String arg0, int arg1) throws JMSException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLongProperty(String arg0, long arg1) throws JMSException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloatProperty(String arg0, float arg1) throws JMSException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDoubleProperty(String arg0, double arg1) throws JMSException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStringProperty(String arg0, String arg1) throws JMSException {
|
||||
props.put(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setObjectProperty(String arg0, Object arg1) throws JMSException {
|
||||
props.put(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acknowledge() throws JMSException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearBody() throws JMSException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String arg0) throws JMSException {
|
||||
text = arg0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() throws JMSException {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
public void testForeignMessage() throws Exception {
|
||||
|
||||
// Receive a message with the JMS API
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
|
||||
// Send the message.
|
||||
{
|
||||
ForeignMessage message = new ForeignMessage();
|
||||
message.text = "Hello";
|
||||
message.setStringProperty("test", "value");
|
||||
long timeToLive = 10000L;
|
||||
long start = System.currentTimeMillis();
|
||||
producer.send(message, Session.AUTO_ACKNOWLEDGE, 7, timeToLive);
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
|
||||
//validate jms spec 1.1 section 3.4.11 table 3.1
|
||||
// JMSDestination, JMSDeliveryMode, JMSExpiration, JMSPriority, JMSMessageID, and JMSTimestamp
|
||||
//must be set by sending a message.
|
||||
|
||||
assertNotNull(message.getJMSDestination());
|
||||
assertEquals(Session.AUTO_ACKNOWLEDGE, message.getJMSDeliveryMode());
|
||||
assertTrue(start + timeToLive <= message.getJMSExpiration());
|
||||
assertTrue(end + timeToLive >= message.getJMSExpiration());
|
||||
assertEquals(7, message.getJMSPriority());
|
||||
assertNotNull(message.getJMSMessageID());
|
||||
assertTrue(start <= message.getJMSTimestamp());
|
||||
assertTrue(end >= message.getJMSTimestamp());
|
||||
}
|
||||
|
||||
// Validate message is OK.
|
||||
{
|
||||
TextMessage message = (TextMessage)consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
assertEquals("Hello", message.getText());
|
||||
assertEquals("value", message.getStringProperty("test"));
|
||||
}
|
||||
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JMSQueueRedeliverTest extends JmsTopicRedeliverTest {
|
||||
protected void setUp() throws Exception {
|
||||
topic = false;
|
||||
super.setUp();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
/**
|
||||
* 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.Enumeration;
|
||||
|
||||
import javax.jms.DeliveryMode;
|
||||
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 junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ActiveMQMessage;
|
||||
|
||||
public class JMSUsecaseTest extends JmsTestSupport {
|
||||
|
||||
public ActiveMQDestination destination;
|
||||
public int deliveryMode;
|
||||
public int prefetch;
|
||||
public byte destinationType;
|
||||
public boolean durableConsumer;
|
||||
|
||||
public static Test suite() {
|
||||
return suite(JMSUsecaseTest.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(suite());
|
||||
}
|
||||
|
||||
public void initCombosForTestQueueBrowser() {
|
||||
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.TEMP_QUEUE_TYPE)});
|
||||
}
|
||||
|
||||
public void testQueueBrowser() throws Exception {
|
||||
|
||||
// Send a message to the broker.
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setDeliveryMode(this.deliveryMode);
|
||||
sendMessages(session, producer, 5);
|
||||
producer.close();
|
||||
|
||||
QueueBrowser browser = session.createBrowser((Queue)destination);
|
||||
Enumeration<?> enumeration = browser.getEnumeration();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
Thread.sleep(100);
|
||||
assertTrue(enumeration.hasMoreElements());
|
||||
Message m = (Message)enumeration.nextElement();
|
||||
assertNotNull(m);
|
||||
assertEquals("" + i, ((TextMessage)m).getText());
|
||||
}
|
||||
assertFalse(enumeration.hasMoreElements());
|
||||
}
|
||||
|
||||
public void initCombosForTestSendReceive() {
|
||||
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 testSendReceive() throws Exception {
|
||||
// Send a message to the broker.
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setDeliveryMode(this.deliveryMode);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
ActiveMQMessage message = new ActiveMQMessage();
|
||||
producer.send(message);
|
||||
|
||||
// Make sure only 1 message was delivered.
|
||||
assertNotNull(consumer.receive(1000));
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void initCombosForTestSendReceiveTransacted() {
|
||||
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 testSendReceiveTransacted() throws Exception {
|
||||
// Send a message to the broker.
|
||||
connection.start();
|
||||
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
destination = createDestination(session, destinationType);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setDeliveryMode(this.deliveryMode);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
producer.send(session.createTextMessage("test"));
|
||||
|
||||
// Message should not be delivered until commit.
|
||||
assertNull(consumer.receiveNoWait());
|
||||
session.commit();
|
||||
|
||||
// Make sure only 1 message was delivered.
|
||||
Message message = consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
assertFalse(message.getJMSRedelivered());
|
||||
assertNull(consumer.receiveNoWait());
|
||||
|
||||
// Message should be redelivered is rollback is used.
|
||||
session.rollback();
|
||||
|
||||
// Make sure only 1 message was delivered.
|
||||
message = consumer.receive(2000);
|
||||
assertNotNull(message);
|
||||
assertTrue(message.getJMSRedelivered());
|
||||
assertNull(consumer.receiveNoWait());
|
||||
|
||||
// If we commit now, the message should not be redelivered.
|
||||
session.commit();
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* 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.ConnectionFactory;
|
||||
import junit.framework.Test;
|
||||
|
||||
/*
|
||||
* allow an XA session to be used as an auto ack session when no XA transaction
|
||||
* https://issues.apache.org/activemq/browse/AMQ-2659
|
||||
*/
|
||||
public class JMSXAConsumerTest extends JMSConsumerTest {
|
||||
|
||||
public static Test suite() {
|
||||
return suite(JMSXAConsumerTest.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQXAConnectionFactory("vm://localhost");
|
||||
}
|
||||
|
||||
// some tests use transactions, these will not work unless an XA transaction is in place
|
||||
// slip these
|
||||
public void testPrefetch1MessageNotDispatched() throws Exception {
|
||||
}
|
||||
|
||||
public void testRedispatchOfUncommittedTx() throws Exception {
|
||||
}
|
||||
|
||||
public void testRedispatchOfRolledbackTx() throws Exception {
|
||||
}
|
||||
|
||||
public void testMessageListenerOnMessageCloseUnackedWithPrefetch1StayInQueue() throws Exception {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* 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.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsAutoAckListenerTest extends TestSupport implements MessageListener {
|
||||
|
||||
private Connection connection;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
connection = createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if acknowleged messages are being consumed.
|
||||
*
|
||||
* @throws javax.jms.JMSException
|
||||
*/
|
||||
public void testAckedMessageAreConsumed() throws Exception {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue("test");
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.send(session.createTextMessage("Hello"));
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
consumer.setMessageListener(this);
|
||||
|
||||
Thread.sleep(10000);
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
// Attempt to Consume the message...check if message was acknowledge
|
||||
consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNull(msg);
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
public void onMessage(Message message) {
|
||||
assertNotNull(message);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* 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.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsAutoAckTest extends TestSupport {
|
||||
|
||||
private Connection connection;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
connection = createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if acknowleged messages are being consumed.
|
||||
*
|
||||
* @throws javax.jms.JMSException
|
||||
*/
|
||||
public void testAckedMessageAreConsumed() throws JMSException {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue("test");
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.send(session.createTextMessage("Hello"));
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
|
||||
// Reset the session.
|
||||
session.close();
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
// Attempt to Consume the message...
|
||||
consumer = session.createConsumer(queue);
|
||||
msg = consumer.receive(1000);
|
||||
assertNull(msg);
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
/**
|
||||
* 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.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
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.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.broker.BrokerFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Benchmarks the broker by starting many consumer and producers against the
|
||||
* same destination. Make sure you run with jvm option -server (makes a big
|
||||
* difference). The tests simulate storing 1000 1k jms messages to see the rate
|
||||
* of processing msg/sec.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JmsBenchmark extends JmsTestSupport {
|
||||
private static final transient Logger LOG = LoggerFactory.getLogger(JmsBenchmark.class);
|
||||
|
||||
private static final long SAMPLE_DELAY = Integer.parseInt(System.getProperty("SAMPLE_DELAY", "" + 1000 * 5));
|
||||
private static final long SAMPLES = Integer.parseInt(System.getProperty("SAMPLES", "10"));
|
||||
private static final long SAMPLE_DURATION = Integer.parseInt(System.getProperty("SAMPLES_DURATION", "" + 1000 * 60));
|
||||
private static final int PRODUCER_COUNT = Integer.parseInt(System.getProperty("PRODUCER_COUNT", "10"));
|
||||
private static final int CONSUMER_COUNT = Integer.parseInt(System.getProperty("CONSUMER_COUNT", "10"));
|
||||
|
||||
public ActiveMQDestination destination;
|
||||
|
||||
public static Test suite() {
|
||||
return suite(JmsBenchmark.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(JmsBenchmark.class);
|
||||
}
|
||||
|
||||
public void initCombos() {
|
||||
addCombinationValues("destination", new Object[] {new ActiveMQQueue("TEST")});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
return BrokerFactory.createBroker(new URI("broker://(tcp://localhost:0)?persistent=false"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionFactory createConnectionFactory() throws URISyntaxException, IOException {
|
||||
return new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getServer().getConnectURI());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Throwable
|
||||
*/
|
||||
public void testConcurrentSendReceive() throws Throwable {
|
||||
|
||||
final Semaphore connectionsEstablished = new Semaphore(1 - (CONSUMER_COUNT + PRODUCER_COUNT));
|
||||
final Semaphore workerDone = new Semaphore(1 - (CONSUMER_COUNT + PRODUCER_COUNT));
|
||||
final CountDownLatch sampleTimeDone = new CountDownLatch(1);
|
||||
|
||||
final AtomicInteger producedMessages = new AtomicInteger(0);
|
||||
final AtomicInteger receivedMessages = new AtomicInteger(0);
|
||||
|
||||
final Callable<Object> producer = new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws JMSException, InterruptedException {
|
||||
Connection connection = factory.createConnection();
|
||||
connections.add(connection);
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
BytesMessage message = session.createBytesMessage();
|
||||
message.writeBytes(new byte[1024]);
|
||||
connection.start();
|
||||
connectionsEstablished.release();
|
||||
|
||||
while (!sampleTimeDone.await(0, TimeUnit.MILLISECONDS)) {
|
||||
producer.send(message);
|
||||
producedMessages.incrementAndGet();
|
||||
}
|
||||
|
||||
connection.close();
|
||||
workerDone.release();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
final Callable<Object> consumer = new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws JMSException, InterruptedException {
|
||||
Connection connection = factory.createConnection();
|
||||
connections.add(connection);
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message msg) {
|
||||
receivedMessages.incrementAndGet();
|
||||
}
|
||||
});
|
||||
connection.start();
|
||||
|
||||
connectionsEstablished.release();
|
||||
sampleTimeDone.await();
|
||||
|
||||
connection.close();
|
||||
workerDone.release();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
final Throwable workerError[] = new Throwable[1];
|
||||
for (int i = 0; i < PRODUCER_COUNT; i++) {
|
||||
new Thread("Producer:" + i) {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
producer.call();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
workerError[0] = e;
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
for (int i = 0; i < CONSUMER_COUNT; i++) {
|
||||
new Thread("Consumer:" + i) {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
consumer.call();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
workerError[0] = e;
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
LOG.info(getName() + ": Waiting for Producers and Consumers to startup.");
|
||||
connectionsEstablished.acquire();
|
||||
LOG.info("Producers and Consumers are now running. Waiting for system to reach steady state: " + (SAMPLE_DELAY / 1000.0f) + " seconds");
|
||||
Thread.sleep(1000 * 10);
|
||||
|
||||
LOG.info("Starting sample: " + SAMPLES + " each lasting " + (SAMPLE_DURATION / 1000.0f) + " seconds");
|
||||
|
||||
for (int i = 0; i < SAMPLES; i++) {
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
producedMessages.set(0);
|
||||
receivedMessages.set(0);
|
||||
|
||||
Thread.sleep(SAMPLE_DURATION);
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
int r = receivedMessages.get();
|
||||
int p = producedMessages.get();
|
||||
|
||||
LOG.info("published: " + p + " msgs at " + (p * 1000f / (end - start)) + " msgs/sec, " + "consumed: " + r + " msgs at " + (r * 1000f / (end - start)) + " msgs/sec");
|
||||
}
|
||||
|
||||
LOG.info("Sample done.");
|
||||
sampleTimeDone.countDown();
|
||||
|
||||
workerDone.acquire();
|
||||
if (workerError[0] != null) {
|
||||
throw workerError[0];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* 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.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsClientAckListenerTest extends TestSupport implements MessageListener {
|
||||
|
||||
private Connection connection;
|
||||
private boolean dontAck;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
connection = createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if acknowleged messages are being consumed.
|
||||
*
|
||||
* @throws javax.jms.JMSException
|
||||
*/
|
||||
public void testAckedMessageAreConsumed() throws Exception {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue("test");
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.send(session.createTextMessage("Hello"));
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
consumer.setMessageListener(this);
|
||||
|
||||
Thread.sleep(10000);
|
||||
|
||||
// Reset the session.
|
||||
session.close();
|
||||
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
|
||||
// Attempt to Consume the message...
|
||||
consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNull(msg);
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if unacknowleged messages are being redelivered when the consumer
|
||||
* connects again.
|
||||
*
|
||||
* @throws javax.jms.JMSException
|
||||
*/
|
||||
public void testUnAckedMessageAreNotConsumedOnSessionClose() throws Exception {
|
||||
connection.start();
|
||||
// don't aknowledge message on onMessage() call
|
||||
dontAck = true;
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue("test");
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.send(session.createTextMessage("Hello"));
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
consumer.setMessageListener(this);
|
||||
// Don't ack the message.
|
||||
|
||||
// Reset the session. This should cause the Unacked message to be
|
||||
// redelivered.
|
||||
session.close();
|
||||
|
||||
Thread.sleep(10000);
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
// Attempt to Consume the message...
|
||||
consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(2000);
|
||||
assertNotNull(msg);
|
||||
msg.acknowledge();
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
public void onMessage(Message message) {
|
||||
|
||||
assertNotNull(message);
|
||||
if (!dontAck) {
|
||||
try {
|
||||
message.acknowledge();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/**
|
||||
* 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.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsClientAckTest extends TestSupport {
|
||||
|
||||
private Connection connection;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
connection = createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if acknowledged messages are being consumed.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testAckedMessageAreConsumed() throws JMSException {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue(getQueueName());
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.send(session.createTextMessage("Hello"));
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
msg.acknowledge();
|
||||
|
||||
// Reset the session.
|
||||
session.close();
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
|
||||
// Attempt to Consume the message...
|
||||
consumer = session.createConsumer(queue);
|
||||
msg = consumer.receive(1000);
|
||||
assertNull(msg);
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if acknowledged messages are being consumed.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testLastMessageAcked() throws JMSException {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue(getQueueName());
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.send(session.createTextMessage("Hello"));
|
||||
producer.send(session.createTextMessage("Hello2"));
|
||||
producer.send(session.createTextMessage("Hello3"));
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
msg.acknowledge();
|
||||
|
||||
// Reset the session.
|
||||
session.close();
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
|
||||
// Attempt to Consume the message...
|
||||
consumer = session.createConsumer(queue);
|
||||
msg = consumer.receive(1000);
|
||||
assertNull(msg);
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if unacknowledged messages are being re-delivered when the consumer connects again.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testUnAckedMessageAreNotConsumedOnSessionClose() throws JMSException {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue(getQueueName());
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.send(session.createTextMessage("Hello"));
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
// Don't ack the message.
|
||||
|
||||
// Reset the session. This should cause the unacknowledged message to be re-delivered.
|
||||
session.close();
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
|
||||
// Attempt to Consume the message...
|
||||
consumer = session.createConsumer(queue);
|
||||
msg = consumer.receive(2000);
|
||||
assertNotNull(msg);
|
||||
msg.acknowledge();
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
protected String getQueueName() {
|
||||
return getClass().getName() + "." + getName();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/**
|
||||
* 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.Random;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.jms.Topic;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsConnectionStartStopTest extends TestSupport {
|
||||
|
||||
private static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory
|
||||
.getLog(JmsConnectionStartStopTest.class);
|
||||
|
||||
private Connection startedConnection;
|
||||
private Connection stoppedConnection;
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
|
||||
LOG.info(getClass().getClassLoader().getResource("log4j.properties"));
|
||||
|
||||
ActiveMQConnectionFactory factory = createConnectionFactory();
|
||||
startedConnection = factory.createConnection();
|
||||
startedConnection.start();
|
||||
stoppedConnection = factory.createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
stoppedConnection.close();
|
||||
startedConnection.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the consumer receives the messages that were sent before the
|
||||
* connection was started.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testStoppedConsumerHoldsMessagesTillStarted() throws JMSException {
|
||||
Session startedSession = startedConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Session stoppedSession = stoppedConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
// Setup the consumers.
|
||||
Topic topic = startedSession.createTopic("test");
|
||||
MessageConsumer startedConsumer = startedSession.createConsumer(topic);
|
||||
MessageConsumer stoppedConsumer = stoppedSession.createConsumer(topic);
|
||||
|
||||
// Send the message.
|
||||
MessageProducer producer = startedSession.createProducer(topic);
|
||||
TextMessage message = startedSession.createTextMessage("Hello");
|
||||
producer.send(message);
|
||||
|
||||
// Test the assertions.
|
||||
Message m = startedConsumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
|
||||
m = stoppedConsumer.receive(1000);
|
||||
assertNull(m);
|
||||
|
||||
stoppedConnection.start();
|
||||
m = stoppedConsumer.receive(5000);
|
||||
assertNotNull(m);
|
||||
|
||||
startedSession.close();
|
||||
stoppedSession.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the consumer is able to receive messages eveb when the
|
||||
* connecction restarts multiple times.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testMultipleConnectionStops() throws Exception {
|
||||
testStoppedConsumerHoldsMessagesTillStarted();
|
||||
stoppedConnection.stop();
|
||||
testStoppedConsumerHoldsMessagesTillStarted();
|
||||
stoppedConnection.stop();
|
||||
testStoppedConsumerHoldsMessagesTillStarted();
|
||||
}
|
||||
|
||||
|
||||
public void testConcurrentSessionCreateWithStart() throws Exception {
|
||||
ThreadPoolExecutor executor = new ThreadPoolExecutor(50, Integer.MAX_VALUE,
|
||||
60L, TimeUnit.SECONDS,
|
||||
new SynchronousQueue<Runnable>());
|
||||
final Vector<Throwable> exceptions = new Vector<Throwable>();
|
||||
final Random rand = new Random();
|
||||
Runnable createSessionTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(rand.nextInt(10));
|
||||
stoppedConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
} catch (Exception e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Runnable startStopTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(rand.nextInt(10));
|
||||
stoppedConnection.start();
|
||||
stoppedConnection.stop();
|
||||
} catch (Exception e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (int i=0; i<1000; i++) {
|
||||
executor.execute(createSessionTask);
|
||||
executor.execute(startStopTask);
|
||||
}
|
||||
|
||||
executor.shutdown();
|
||||
assertTrue("executor terminated", executor.awaitTermination(30, TimeUnit.SECONDS));
|
||||
assertTrue("no exceptions: " + exceptions, exceptions.isEmpty());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
/**
|
||||
* 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.Vector;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
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.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
||||
public class JmsConsumerResetActiveListenerTest extends TestCase {
|
||||
|
||||
private Connection connection;
|
||||
private ActiveMQConnectionFactory factory;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
factory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
connection = factory.createConnection();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* verify the (undefined by spec) behaviour of setting a listener while receiving a message.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSetListenerFromListener() throws Exception {
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Destination dest = session.createQueue("Queue-" + getName());
|
||||
final MessageConsumer consumer = session.createConsumer(dest);
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(2);
|
||||
final AtomicBoolean first = new AtomicBoolean(true);
|
||||
final Vector<Object> results = new Vector<Object>();
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
|
||||
public void onMessage(Message message) {
|
||||
if (first.compareAndSet(true, false)) {
|
||||
try {
|
||||
consumer.setMessageListener(this);
|
||||
results.add(message);
|
||||
} catch (JMSException e) {
|
||||
results.add(e);
|
||||
}
|
||||
} else {
|
||||
results.add(message);
|
||||
}
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
connection.start();
|
||||
|
||||
MessageProducer producer = session.createProducer(dest);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
producer.send(session.createTextMessage("First"));
|
||||
producer.send(session.createTextMessage("Second"));
|
||||
|
||||
assertTrue("we did not timeout", latch.await(5, TimeUnit.SECONDS));
|
||||
|
||||
assertEquals("we have a result", 2, results.size());
|
||||
Object result = results.get(0);
|
||||
assertTrue(result instanceof TextMessage);
|
||||
assertEquals("result is first", "First", ((TextMessage)result).getText());
|
||||
result = results.get(1);
|
||||
assertTrue(result instanceof TextMessage);
|
||||
assertEquals("result is first", "Second", ((TextMessage)result).getText());
|
||||
}
|
||||
|
||||
/**
|
||||
* and a listener on a new consumer, just in case.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testNewConsumerSetListenerFromListener() throws Exception {
|
||||
final Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
final Destination dest = session.createQueue("Queue-" + getName());
|
||||
final MessageConsumer consumer = session.createConsumer(dest);
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(2);
|
||||
final AtomicBoolean first = new AtomicBoolean(true);
|
||||
final Vector<Object> results = new Vector<Object>();
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
|
||||
public void onMessage(Message message) {
|
||||
if (first.compareAndSet(true, false)) {
|
||||
try {
|
||||
MessageConsumer anotherConsumer = session.createConsumer(dest);
|
||||
anotherConsumer.setMessageListener(this);
|
||||
results.add(message);
|
||||
} catch (JMSException e) {
|
||||
results.add(e);
|
||||
}
|
||||
} else {
|
||||
results.add(message);
|
||||
}
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
connection.start();
|
||||
|
||||
MessageProducer producer = session.createProducer(dest);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
producer.send(session.createTextMessage("First"));
|
||||
producer.send(session.createTextMessage("Second"));
|
||||
|
||||
assertTrue("we did not timeout", latch.await(5, TimeUnit.SECONDS));
|
||||
|
||||
assertEquals("we have a result", 2, results.size());
|
||||
Object result = results.get(0);
|
||||
assertTrue(result instanceof TextMessage);
|
||||
assertEquals("result is first", "First", ((TextMessage)result).getText());
|
||||
result = results.get(1);
|
||||
assertTrue(result instanceof TextMessage);
|
||||
assertEquals("result is first", "Second", ((TextMessage)result).getText());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* 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.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.Topic;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsCreateConsumerInOnMessageTest extends TestSupport implements MessageListener {
|
||||
|
||||
private Connection connection;
|
||||
private Session publisherSession;
|
||||
private Session consumerSession;
|
||||
private MessageConsumer consumer;
|
||||
private MessageConsumer testConsumer;
|
||||
private MessageProducer producer;
|
||||
private Topic topic;
|
||||
private Object lock = new Object();
|
||||
|
||||
/*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
super.topic = true;
|
||||
connection = createConnection();
|
||||
connection.setClientID("connection:" + getSubject());
|
||||
publisherSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
consumerSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
topic = (Topic)super.createDestination("Test.Topic");
|
||||
consumer = consumerSession.createConsumer(topic);
|
||||
consumer.setMessageListener(this);
|
||||
producer = publisherSession.createProducer(topic);
|
||||
connection.start();
|
||||
}
|
||||
|
||||
/*
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
connection.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a consumer can be created asynchronusly
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testCreateConsumer() throws Exception {
|
||||
Message msg = super.createMessage();
|
||||
producer.send(msg);
|
||||
if (testConsumer == null) {
|
||||
synchronized (lock) {
|
||||
lock.wait(3000);
|
||||
}
|
||||
}
|
||||
assertTrue(testConsumer != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the asynchronous subscription mechanism
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public void onMessage(Message message) {
|
||||
try {
|
||||
testConsumer = consumerSession.createConsumer(topic);
|
||||
consumerSession.createProducer(topic);
|
||||
synchronized (lock) {
|
||||
lock.notify();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
assertTrue(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* 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.DeliveryMode;
|
||||
|
||||
import org.apache.activemq.test.JmsTopicSendReceiveTest;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsDurableQueueWildcardSendReceiveTest extends JmsTopicSendReceiveTest {
|
||||
|
||||
/**
|
||||
* Set up the test with a queue and persistent delivery mode.
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
topic = false;
|
||||
deliveryMode = DeliveryMode.PERSISTENT;
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the consumer subject.
|
||||
*/
|
||||
protected String getConsumerSubject() {
|
||||
return "FOO.>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the producer subject.
|
||||
*/
|
||||
protected String getProducerSubject() {
|
||||
return "FOO.BAR.HUMBUG";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsDurableTopicSelectorTest extends JmsTopicSelectorTest {
|
||||
public void setUp() throws Exception {
|
||||
durable = true;
|
||||
super.setUp();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* 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.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.test.JmsTopicSendReceiveTest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsDurableTopicSendReceiveTest extends JmsTopicSendReceiveTest {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JmsDurableTopicSendReceiveTest.class);
|
||||
|
||||
protected Connection connection2;
|
||||
protected Session session2;
|
||||
protected Session consumeSession2;
|
||||
protected MessageConsumer consumer2;
|
||||
protected MessageProducer producer2;
|
||||
protected Destination consumerDestination2;
|
||||
protected Destination producerDestination2;
|
||||
|
||||
/**
|
||||
* Set up a durable suscriber test.
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
this.durable = true;
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if all the messages sent are being received.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSendWhileClosed() throws Exception {
|
||||
connection2 = createConnection();
|
||||
connection2.setClientID("test");
|
||||
connection2.start();
|
||||
session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
producer2 = session2.createProducer(null);
|
||||
producer2.setDeliveryMode(deliveryMode);
|
||||
producerDestination2 = session2.createTopic(getProducerSubject() + "2");
|
||||
Thread.sleep(1000);
|
||||
|
||||
consumeSession2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
consumerDestination2 = session2.createTopic(getConsumerSubject() + "2");
|
||||
consumer2 = consumeSession2.createDurableSubscriber((Topic)consumerDestination2, getName());
|
||||
Thread.sleep(1000);
|
||||
consumer2.close();
|
||||
TextMessage message = session2.createTextMessage("test");
|
||||
message.setStringProperty("test", "test");
|
||||
message.setJMSType("test");
|
||||
producer2.send(producerDestination2, message);
|
||||
LOG.info("Creating durable consumer");
|
||||
consumer2 = consumeSession2.createDurableSubscriber((Topic)consumerDestination2, getName());
|
||||
Message msg = consumer2.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertEquals(((TextMessage)msg).getText(), "test");
|
||||
assertEquals(msg.getJMSType(), "test");
|
||||
assertEquals(msg.getStringProperty("test"), "test");
|
||||
connection2.stop();
|
||||
connection2.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* 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.DeliveryMode;
|
||||
|
||||
import org.apache.activemq.test.JmsResourceProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsDurableTopicTransactionTest extends JmsTopicTransactionTest {
|
||||
|
||||
/**
|
||||
* @see JmsTransactionTestSupport#getJmsResourceProvider()
|
||||
*/
|
||||
protected JmsResourceProvider getJmsResourceProvider() {
|
||||
JmsResourceProvider provider = new JmsResourceProvider();
|
||||
provider.setTopic(true);
|
||||
provider.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
provider.setClientID(getClass().getName());
|
||||
provider.setDurableName(getName());
|
||||
return provider;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* 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.DeliveryMode;
|
||||
|
||||
import org.apache.activemq.test.JmsTopicSendReceiveTest;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsDurableTopicWildcardSendReceiveTest extends JmsTopicSendReceiveTest {
|
||||
|
||||
/**
|
||||
* Sets up a test with a topic destination, durable suscriber and persistent
|
||||
* delivery mode.
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
topic = true;
|
||||
durable = true;
|
||||
deliveryMode = DeliveryMode.PERSISTENT;
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the consumer subject.
|
||||
*/
|
||||
protected String getConsumerSubject() {
|
||||
return "FOO.>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the producer subject.
|
||||
*/
|
||||
protected String getProducerSubject() {
|
||||
return "FOO.BAR.HUMBUG";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
/**
|
||||
* 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 static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
public class JmsMessageConsumerTest {
|
||||
|
||||
private BrokerService brokerService;
|
||||
private String brokerURI;
|
||||
|
||||
@Rule public TestName name = new TestName();
|
||||
|
||||
@Before
|
||||
public void startBroker() throws Exception {
|
||||
brokerService = new BrokerService();
|
||||
brokerService.setPersistent(false);
|
||||
brokerService.setUseJmx(false);
|
||||
brokerService.start();
|
||||
brokerService.waitUntilStarted();
|
||||
|
||||
brokerURI = "vm://localhost?create=false";
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopBroker() throws Exception {
|
||||
if (brokerService != null) {
|
||||
brokerService.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncReceiveWithExpirationChecks() throws Exception {
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerURI);
|
||||
|
||||
Connection connection = factory.createConnection();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination = session.createQueue(name.getMethodName());
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setTimeToLive(TimeUnit.SECONDS.toMillis(2));
|
||||
connection.start();
|
||||
|
||||
producer.send(session.createTextMessage("test"));
|
||||
|
||||
// Allow message to expire in the prefetch buffer
|
||||
TimeUnit.SECONDS.sleep(4);
|
||||
|
||||
assertNull(consumer.receive(1000));
|
||||
connection.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncReceiveWithIgnoreExpirationChecks() throws Exception {
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerURI);
|
||||
factory.setConsumerExpiryCheckEnabled(false);
|
||||
|
||||
Connection connection = factory.createConnection();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination = session.createQueue(name.getMethodName());
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setTimeToLive(TimeUnit.SECONDS.toMillis(2));
|
||||
connection.start();
|
||||
|
||||
producer.send(session.createTextMessage("test"));
|
||||
|
||||
// Allow message to expire in the prefetch buffer
|
||||
TimeUnit.SECONDS.sleep(4);
|
||||
|
||||
assertNotNull(consumer.receive(1000));
|
||||
connection.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsyncReceiveWithExpirationChecks() throws Exception {
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerURI);
|
||||
|
||||
final CountDownLatch received = new CountDownLatch(1);
|
||||
|
||||
Connection connection = factory.createConnection();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination = session.createQueue(name.getMethodName());
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
received.countDown();
|
||||
}
|
||||
});
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setTimeToLive(TimeUnit.SECONDS.toMillis(2));
|
||||
|
||||
producer.send(session.createTextMessage("test"));
|
||||
|
||||
// Allow message to expire in the prefetch buffer
|
||||
TimeUnit.SECONDS.sleep(4);
|
||||
connection.start();
|
||||
|
||||
assertFalse(received.await(1, TimeUnit.SECONDS));
|
||||
connection.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsyncReceiveWithoutExpirationChecks() throws Exception {
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerURI);
|
||||
factory.setConsumerExpiryCheckEnabled(false);
|
||||
|
||||
final CountDownLatch received = new CountDownLatch(1);
|
||||
|
||||
Connection connection = factory.createConnection();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination = session.createQueue(name.getMethodName());
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
received.countDown();
|
||||
}
|
||||
});
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setTimeToLive(TimeUnit.SECONDS.toMillis(2));
|
||||
|
||||
producer.send(session.createTextMessage("test"));
|
||||
|
||||
// Allow message to expire in the prefetch buffer
|
||||
TimeUnit.SECONDS.sleep(4);
|
||||
connection.start();
|
||||
|
||||
assertTrue(received.await(5, TimeUnit.SECONDS));
|
||||
connection.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,641 @@
|
|||
/**
|
||||
* 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.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 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 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() {
|
||||
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)}.
|
||||
*
|
||||
* @see #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
|
||||
*/
|
||||
protected void waitForBridge(final String localBrokerName,
|
||||
final String remoteBrokerName, long time, TimeUnit units)
|
||||
throws InterruptedException, TimeoutException, Exception {
|
||||
if (!Wait.waitFor(new Wait.Condition() {
|
||||
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(){
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
brokers = new HashMap<String, BrokerItem>();
|
||||
destinations = new HashMap<String, Destination>();
|
||||
}
|
||||
|
||||
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((Topic)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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,335 @@
|
|||
/**
|
||||
* 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.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
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.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.jms.TopicSubscriber;
|
||||
|
||||
import org.apache.activemq.broker.BrokerFactory;
|
||||
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.apache.activemq.util.MessageIdList;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TestName;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Test case support used to test multiple message comsumers and message
|
||||
* producers connecting to a single broker.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JmsMultipleClientsTestSupport {
|
||||
|
||||
@Rule
|
||||
public TestName testName = new TestName();
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(JmsMultipleClientsTestSupport.class);
|
||||
|
||||
protected Map<MessageConsumer, MessageIdList> consumers = new HashMap<MessageConsumer, MessageIdList>(); // Map of consumer with messages
|
||||
// received
|
||||
protected int consumerCount = 1;
|
||||
protected int producerCount = 1;
|
||||
|
||||
protected int messageSize = 1024;
|
||||
|
||||
protected boolean useConcurrentSend = true;
|
||||
protected boolean autoFail = true;
|
||||
protected boolean durable;
|
||||
public boolean topic;
|
||||
protected boolean persistent;
|
||||
|
||||
protected BrokerService broker;
|
||||
protected Destination destination;
|
||||
protected List<Connection> connections = Collections.synchronizedList(new ArrayList<Connection>());
|
||||
protected MessageIdList allMessagesList = new MessageIdList();
|
||||
|
||||
private AtomicInteger producerLock;
|
||||
|
||||
protected void startProducers(Destination dest, int msgCount) throws Exception {
|
||||
startProducers(createConnectionFactory(), dest, msgCount);
|
||||
}
|
||||
|
||||
protected void startProducers(final ConnectionFactory factory, final Destination dest, final int msgCount) throws Exception {
|
||||
// Use concurrent send
|
||||
if (useConcurrentSend) {
|
||||
producerLock = new AtomicInteger(producerCount);
|
||||
|
||||
for (int i = 0; i < producerCount; i++) {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
sendMessages(factory.createConnection(), dest, msgCount);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
synchronized (producerLock) {
|
||||
producerLock.decrementAndGet();
|
||||
producerLock.notifyAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
t.start();
|
||||
}
|
||||
|
||||
// Wait for all producers to finish sending
|
||||
synchronized (producerLock) {
|
||||
while (producerLock.get() != 0) {
|
||||
producerLock.wait(2000);
|
||||
}
|
||||
}
|
||||
|
||||
// Use serialized send
|
||||
} else {
|
||||
for (int i = 0; i < producerCount; i++) {
|
||||
sendMessages(factory.createConnection(), dest, msgCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendMessages(Connection connection, Destination destination, int count) throws Exception {
|
||||
connections.add(connection);
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setDeliveryMode(persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
TextMessage msg = createTextMessage(session, "" + i);
|
||||
producer.send(msg);
|
||||
}
|
||||
|
||||
producer.close();
|
||||
session.close();
|
||||
connection.close();
|
||||
}
|
||||
|
||||
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 void startConsumers(Destination dest) throws Exception {
|
||||
startConsumers(createConnectionFactory(), dest);
|
||||
}
|
||||
|
||||
protected void startConsumers(ConnectionFactory factory, Destination dest) throws Exception {
|
||||
MessageConsumer consumer;
|
||||
for (int i = 0; i < consumerCount; i++) {
|
||||
if (durable && topic) {
|
||||
consumer = createDurableSubscriber(factory.createConnection(), dest, "consumer" + (i + 1));
|
||||
} else {
|
||||
consumer = createMessageConsumer(factory.createConnection(), dest);
|
||||
}
|
||||
MessageIdList list = new MessageIdList();
|
||||
list.setParent(allMessagesList);
|
||||
consumer.setMessageListener(list);
|
||||
consumers.put(consumer, list);
|
||||
}
|
||||
}
|
||||
|
||||
protected MessageConsumer createMessageConsumer(Connection conn, Destination dest) throws Exception {
|
||||
connections.add(conn);
|
||||
|
||||
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final MessageConsumer consumer = sess.createConsumer(dest);
|
||||
conn.start();
|
||||
|
||||
return consumer;
|
||||
}
|
||||
|
||||
protected TopicSubscriber createDurableSubscriber(Connection conn, Destination dest, String name) throws Exception {
|
||||
conn.setClientID(name);
|
||||
connections.add(conn);
|
||||
conn.start();
|
||||
|
||||
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final TopicSubscriber consumer = sess.createDurableSubscriber((javax.jms.Topic)dest, name);
|
||||
|
||||
return consumer;
|
||||
}
|
||||
|
||||
protected void waitForAllMessagesToBeReceived(int messageCount) throws Exception {
|
||||
allMessagesList.waitForMessagesToArrive(messageCount);
|
||||
}
|
||||
|
||||
protected ActiveMQDestination createDestination() throws JMSException {
|
||||
String name = "." + getClass().getName() + "." + getName();
|
||||
// ensure not inadvertently composite because of combos
|
||||
name = name.replace(' ','_');
|
||||
name = name.replace(',','&');
|
||||
if (topic) {
|
||||
destination = new ActiveMQTopic("Topic" + name);
|
||||
return (ActiveMQDestination)destination;
|
||||
} else {
|
||||
destination = new ActiveMQQueue("Queue" + name);
|
||||
return (ActiveMQDestination)destination;
|
||||
}
|
||||
}
|
||||
|
||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory("vm://localhost");
|
||||
}
|
||||
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
return BrokerFactory.createBroker(new URI("broker://()/localhost?persistent=false&useJmx=true"));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
broker = createBroker();
|
||||
broker.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
for (Iterator<Connection> iter = connections.iterator(); iter.hasNext();) {
|
||||
Connection conn = iter.next();
|
||||
try {
|
||||
conn.close();
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
if (broker !=null ) { // FIXME remove
|
||||
broker.stop();
|
||||
allMessagesList.flushMessages();
|
||||
consumers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some helpful assertions for multiple consumers.
|
||||
*/
|
||||
protected void assertConsumerReceivedAtLeastXMessages(MessageConsumer consumer, int msgCount) {
|
||||
MessageIdList messageIdList = consumers.get(consumer);
|
||||
messageIdList.assertAtLeastMessagesReceived(msgCount);
|
||||
}
|
||||
|
||||
protected void assertConsumerReceivedAtMostXMessages(MessageConsumer consumer, int msgCount) {
|
||||
MessageIdList messageIdList = consumers.get(consumer);
|
||||
messageIdList.assertAtMostMessagesReceived(msgCount);
|
||||
}
|
||||
|
||||
protected void assertConsumerReceivedXMessages(MessageConsumer consumer, int msgCount) {
|
||||
MessageIdList messageIdList = consumers.get(consumer);
|
||||
messageIdList.assertMessagesReceivedNoWait(msgCount);
|
||||
}
|
||||
|
||||
protected void assertEachConsumerReceivedAtLeastXMessages(int msgCount) {
|
||||
for (Iterator<MessageConsumer> i = consumers.keySet().iterator(); i.hasNext();) {
|
||||
assertConsumerReceivedAtLeastXMessages(i.next(), msgCount);
|
||||
}
|
||||
}
|
||||
|
||||
protected void assertEachConsumerReceivedAtMostXMessages(int msgCount) {
|
||||
for (Iterator<MessageConsumer> i = consumers.keySet().iterator(); i.hasNext();) {
|
||||
assertConsumerReceivedAtMostXMessages(i.next(), msgCount);
|
||||
}
|
||||
}
|
||||
|
||||
protected void assertEachConsumerReceivedXMessages(int msgCount) {
|
||||
for (Iterator<MessageConsumer> i = consumers.keySet().iterator(); i.hasNext();) {
|
||||
assertConsumerReceivedXMessages(i.next(), msgCount);
|
||||
}
|
||||
}
|
||||
|
||||
protected void assertTotalMessagesReceived(int msgCount) {
|
||||
allMessagesList.assertMessagesReceivedNoWait(msgCount);
|
||||
|
||||
// now lets count the individual messages received
|
||||
int totalMsg = 0;
|
||||
for (Iterator<MessageConsumer> i = consumers.keySet().iterator(); i.hasNext();) {
|
||||
MessageIdList messageIdList = consumers.get(i.next());
|
||||
totalMsg += messageIdList.getMessageCount();
|
||||
}
|
||||
assertEquals("Total of consumers message count", msgCount, totalMsg);
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return getName(false);
|
||||
}
|
||||
|
||||
public String getName(boolean original) {
|
||||
String currentTestName = testName.getMethodName();
|
||||
currentTestName = currentTestName.replace("[","");
|
||||
currentTestName = currentTestName.replace("]","");
|
||||
return currentTestName;
|
||||
}
|
||||
|
||||
public void assertDestinationMemoryUsageGoesToZero() throws Exception {
|
||||
assertEquals("destination memory is back to 0", 0,
|
||||
TestSupport.getDestination(broker, ActiveMQDestination.transform(destination)).getMemoryUsage().getPercentUsage());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This is copied from AutoFailTestSupport. We may want to move it to someplace where more
|
||||
* tests can use it.
|
||||
*/
|
||||
public static void dumpAllThreads(String prefix) {
|
||||
Map<Thread, StackTraceElement[]> stacks = Thread.getAllStackTraces();
|
||||
for (Map.Entry<Thread, StackTraceElement[]> stackEntry : stacks.entrySet()) {
|
||||
System.err.println(prefix + " " + stackEntry.getKey());
|
||||
for(StackTraceElement element : stackEntry.getValue()) {
|
||||
System.err.println(" " + element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,448 @@
|
|||
/**
|
||||
* 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.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.QueueBrowser;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import javax.management.openmbean.TabularData;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.jmx.QueueViewMBean;
|
||||
import org.apache.activemq.broker.region.BaseDestination;
|
||||
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 JmsQueueBrowserTest extends JmsTestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ActiveMQXAConnectionFactoryTest.class);
|
||||
public boolean isUseCache = false;
|
||||
|
||||
public static Test suite() throws Exception {
|
||||
return suite(JmsQueueBrowserTest.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the queue browser. Browses the messages then the consumer tries to receive them. The messages should still
|
||||
* be in the queue even when it was browsed.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testReceiveBrowseReceive() throws Exception {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
ActiveMQQueue destination = new ActiveMQQueue("TEST");
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
connection.start();
|
||||
|
||||
Message[] outbound = new Message[]{session.createTextMessage("First Message"),
|
||||
session.createTextMessage("Second Message"),
|
||||
session.createTextMessage("Third Message")};
|
||||
|
||||
// lets consume any outstanding messages from previous test runs
|
||||
while (consumer.receive(1000) != null) {
|
||||
}
|
||||
|
||||
producer.send(outbound[0]);
|
||||
producer.send(outbound[1]);
|
||||
producer.send(outbound[2]);
|
||||
|
||||
// Get the first.
|
||||
assertEquals(outbound[0], consumer.receive(1000));
|
||||
consumer.close();
|
||||
|
||||
QueueBrowser browser = session.createBrowser(destination);
|
||||
Enumeration<?> enumeration = browser.getEnumeration();
|
||||
|
||||
// browse the second
|
||||
assertTrue("should have received the second message", enumeration.hasMoreElements());
|
||||
assertEquals(outbound[1], enumeration.nextElement());
|
||||
|
||||
// browse the third.
|
||||
assertTrue("Should have received the third message", enumeration.hasMoreElements());
|
||||
assertEquals(outbound[2], enumeration.nextElement());
|
||||
|
||||
// There should be no more.
|
||||
boolean tooMany = false;
|
||||
while (enumeration.hasMoreElements()) {
|
||||
LOG.info("Got extra message: " + ((TextMessage) enumeration.nextElement()).getText());
|
||||
tooMany = true;
|
||||
}
|
||||
assertFalse(tooMany);
|
||||
browser.close();
|
||||
|
||||
// Re-open the consumer.
|
||||
consumer = session.createConsumer(destination);
|
||||
// Receive the second.
|
||||
assertEquals(outbound[1], consumer.receive(1000));
|
||||
// Receive the third.
|
||||
assertEquals(outbound[2], consumer.receive(1000));
|
||||
consumer.close();
|
||||
}
|
||||
|
||||
public void initCombosForTestBatchSendBrowseReceive() {
|
||||
addCombinationValues("isUseCache", new Boolean[]{Boolean.TRUE, Boolean.FALSE});
|
||||
}
|
||||
|
||||
public void testBatchSendBrowseReceive() throws Exception {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
ActiveMQQueue destination = new ActiveMQQueue("TEST");
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
connection.start();
|
||||
|
||||
TextMessage[] outbound = new TextMessage[10];
|
||||
for (int i=0; i<10; i++) {
|
||||
outbound[i] = session.createTextMessage( i + " Message");
|
||||
};
|
||||
|
||||
// lets consume any outstanding messages from previous test runs
|
||||
while (consumer.receive(1000) != null) {
|
||||
}
|
||||
consumer.close();
|
||||
|
||||
for (int i=0;i<outbound.length; i++) {
|
||||
producer.send(outbound[i]);
|
||||
}
|
||||
|
||||
QueueBrowser browser = session.createBrowser(destination);
|
||||
Enumeration<?> enumeration = browser.getEnumeration();
|
||||
|
||||
for (int i=0; i<outbound.length; i++) {
|
||||
assertTrue("should have a", enumeration.hasMoreElements());
|
||||
assertEquals(outbound[i], enumeration.nextElement());
|
||||
}
|
||||
browser.close();
|
||||
|
||||
for (int i=0;i<outbound.length; i++) {
|
||||
producer.send(outbound[i]);
|
||||
}
|
||||
|
||||
// verify second batch is visible to browse
|
||||
browser = session.createBrowser(destination);
|
||||
enumeration = browser.getEnumeration();
|
||||
for (int j=0; j<2;j++) {
|
||||
for (int i=0; i<outbound.length; i++) {
|
||||
assertTrue("should have a", enumeration.hasMoreElements());
|
||||
assertEquals("j=" + j + ", i=" + i, outbound[i].getText(), ((TextMessage) enumeration.nextElement()).getText());
|
||||
}
|
||||
}
|
||||
browser.close();
|
||||
|
||||
consumer = session.createConsumer(destination);
|
||||
for (int i=0; i<outbound.length * 2; i++) {
|
||||
assertNotNull("Got message: " + i, consumer.receive(2000));
|
||||
}
|
||||
consumer.close();
|
||||
}
|
||||
|
||||
public void initCombosForTestBatchSendJmxBrowseReceive() {
|
||||
addCombinationValues("isUseCache", new Boolean[]{Boolean.TRUE, Boolean.FALSE});
|
||||
}
|
||||
|
||||
public void testBatchSendJmxBrowseReceive() throws Exception {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
ActiveMQQueue destination = new ActiveMQQueue("TEST");
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
connection.start();
|
||||
|
||||
TextMessage[] outbound = new TextMessage[10];
|
||||
for (int i=0; i<10; i++) {
|
||||
outbound[i] = session.createTextMessage( i + " Message");
|
||||
};
|
||||
|
||||
// lets consume any outstanding messages from previous test runs
|
||||
while (consumer.receive(1000) != null) {
|
||||
}
|
||||
consumer.close();
|
||||
|
||||
for (int i=0;i<outbound.length; i++) {
|
||||
producer.send(outbound[i]);
|
||||
}
|
||||
|
||||
ObjectName queueViewMBeanName = new ObjectName("org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=TEST");
|
||||
|
||||
LOG.info("Create QueueView MBean...");
|
||||
QueueViewMBean proxy = (QueueViewMBean) broker.getManagementContext().newProxyInstance(queueViewMBeanName, QueueViewMBean.class, true);
|
||||
|
||||
long concount = proxy.getConsumerCount();
|
||||
LOG.info("Consumer Count :" + concount);
|
||||
long messcount = proxy.getQueueSize();
|
||||
LOG.info("current number of messages in the queue :" + messcount);
|
||||
|
||||
// lets browse
|
||||
CompositeData[] compdatalist = proxy.browse();
|
||||
if (compdatalist.length == 0) {
|
||||
fail("There is no message in the queue:");
|
||||
}
|
||||
String[] messageIDs = new String[compdatalist.length];
|
||||
|
||||
for (int i = 0; i < compdatalist.length; i++) {
|
||||
CompositeData cdata = compdatalist[i];
|
||||
|
||||
if (i == 0) {
|
||||
LOG.info("Columns: " + cdata.getCompositeType().keySet());
|
||||
}
|
||||
messageIDs[i] = (String)cdata.get("JMSMessageID");
|
||||
LOG.info("message " + i + " : " + cdata.values());
|
||||
}
|
||||
|
||||
TabularData table = proxy.browseAsTable();
|
||||
LOG.info("Found tabular data: " + table);
|
||||
assertTrue("Table should not be empty!", table.size() > 0);
|
||||
|
||||
assertEquals("Queue size", outbound.length, proxy.getQueueSize());
|
||||
assertEquals("Queue size", outbound.length, compdatalist.length);
|
||||
assertEquals("Queue size", outbound.length, table.size());
|
||||
|
||||
|
||||
LOG.info("Send another 10");
|
||||
for (int i=0;i<outbound.length; i++) {
|
||||
producer.send(outbound[i]);
|
||||
}
|
||||
|
||||
LOG.info("Browse again");
|
||||
|
||||
messcount = proxy.getQueueSize();
|
||||
LOG.info("current number of messages in the queue :" + messcount);
|
||||
|
||||
compdatalist = proxy.browse();
|
||||
if (compdatalist.length == 0) {
|
||||
fail("There is no message in the queue:");
|
||||
}
|
||||
messageIDs = new String[compdatalist.length];
|
||||
|
||||
for (int i = 0; i < compdatalist.length; i++) {
|
||||
CompositeData cdata = compdatalist[i];
|
||||
|
||||
if (i == 0) {
|
||||
LOG.info("Columns: " + cdata.getCompositeType().keySet());
|
||||
}
|
||||
messageIDs[i] = (String)cdata.get("JMSMessageID");
|
||||
LOG.info("message " + i + " : " + cdata.values());
|
||||
}
|
||||
|
||||
table = proxy.browseAsTable();
|
||||
LOG.info("Found tabular data: " + table);
|
||||
assertTrue("Table should not be empty!", table.size() > 0);
|
||||
|
||||
assertEquals("Queue size", outbound.length*2, proxy.getQueueSize());
|
||||
assertEquals("Queue size", outbound.length*2, compdatalist.length);
|
||||
assertEquals("Queue size", outbound.length * 2, table.size());
|
||||
|
||||
consumer = session.createConsumer(destination);
|
||||
for (int i=0; i<outbound.length * 2; i++) {
|
||||
assertNotNull("Got message: " + i, consumer.receive(2000));
|
||||
}
|
||||
consumer.close();
|
||||
}
|
||||
|
||||
public void testBrowseReceive() throws Exception {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
ActiveMQQueue destination = new ActiveMQQueue("TEST");
|
||||
|
||||
connection.start();
|
||||
|
||||
// create consumer
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
// lets consume any outstanding messages from previous test runs
|
||||
while (consumer.receive(1000) != null) {
|
||||
}
|
||||
|
||||
Message[] outbound = new Message[]{session.createTextMessage("First Message"),
|
||||
session.createTextMessage("Second Message"),
|
||||
session.createTextMessage("Third Message")};
|
||||
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.send(outbound[0]);
|
||||
|
||||
// create browser first
|
||||
QueueBrowser browser = session.createBrowser(destination);
|
||||
Enumeration<?> enumeration = browser.getEnumeration();
|
||||
|
||||
// browse the first message
|
||||
assertTrue("should have received the first message", enumeration.hasMoreElements());
|
||||
assertEquals(outbound[0], enumeration.nextElement());
|
||||
|
||||
// Receive the first message.
|
||||
assertEquals(outbound[0], consumer.receive(1000));
|
||||
consumer.close();
|
||||
browser.close();
|
||||
producer.close();
|
||||
}
|
||||
|
||||
public void testLargeNumberOfMessages() throws Exception {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
ActiveMQQueue destination = new ActiveMQQueue("TEST");
|
||||
connection.start();
|
||||
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
|
||||
int numberOfMessages = 4096;
|
||||
|
||||
for (int i = 0; i < numberOfMessages; i++) {
|
||||
producer.send(session.createTextMessage("Message: " + i));
|
||||
}
|
||||
|
||||
QueueBrowser browser = session.createBrowser(destination);
|
||||
Enumeration<?> enumeration = browser.getEnumeration();
|
||||
|
||||
assertTrue(enumeration.hasMoreElements());
|
||||
|
||||
int numberBrowsed = 0;
|
||||
|
||||
while (enumeration.hasMoreElements()) {
|
||||
Message browsed = (Message) enumeration.nextElement();
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Browsed Message [{}]", browsed.getJMSMessageID());
|
||||
}
|
||||
|
||||
numberBrowsed++;
|
||||
}
|
||||
|
||||
System.out.println("Number browsed: " + numberBrowsed);
|
||||
assertEquals(numberOfMessages, numberBrowsed);
|
||||
browser.close();
|
||||
producer.close();
|
||||
}
|
||||
|
||||
public void testQueueBrowserWith2Consumers() throws Exception {
|
||||
final int numMessages = 1000;
|
||||
connection.setAlwaysSyncSend(false);
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
ActiveMQQueue destination = new ActiveMQQueue("TEST");
|
||||
ActiveMQQueue destinationPrefetch10 = new ActiveMQQueue("TEST?jms.prefetchSize=10");
|
||||
ActiveMQQueue destinationPrefetch1 = new ActiveMQQueue("TEST?jms.prefetchsize=1");
|
||||
connection.start();
|
||||
|
||||
ActiveMQConnection connection2 = (ActiveMQConnection)factory.createConnection(userName, password);
|
||||
connection2.start();
|
||||
connections.add(connection2);
|
||||
Session session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
MessageConsumer consumer = session.createConsumer(destinationPrefetch10);
|
||||
|
||||
// lets consume any outstanding messages from previous test runs
|
||||
while (consumer.receive(1000) != null) {
|
||||
}
|
||||
|
||||
for (int i=0; i<numMessages; i++) {
|
||||
TextMessage message = session.createTextMessage("Message: " + i);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
QueueBrowser browser = session2.createBrowser(destinationPrefetch1);
|
||||
@SuppressWarnings("unchecked")
|
||||
Enumeration<Message> browserView = browser.getEnumeration();
|
||||
|
||||
List<Message> messages = new ArrayList<Message>();
|
||||
for (int i = 0; i < numMessages; i++) {
|
||||
Message m1 = consumer.receive(5000);
|
||||
assertNotNull("m1 is null for index: " + i, m1);
|
||||
messages.add(m1);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (; i < numMessages && browserView.hasMoreElements(); i++) {
|
||||
Message m1 = messages.get(i);
|
||||
Message m2 = browserView.nextElement();
|
||||
assertNotNull("m2 is null for index: " + i, m2);
|
||||
assertEquals(m1.getJMSMessageID(), m2.getJMSMessageID());
|
||||
}
|
||||
|
||||
// currently browse max page size is ignored for a queue browser consumer
|
||||
// only guarantee is a page size - but a snapshot of pagedinpending is
|
||||
// used so it is most likely more
|
||||
assertTrue("got at least our expected minimum in the browser: ", i > BaseDestination.MAX_PAGE_SIZE);
|
||||
|
||||
assertFalse("nothing left in the browser", browserView.hasMoreElements());
|
||||
assertNull("consumer finished", consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void testBrowseClose() throws Exception {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
ActiveMQQueue destination = new ActiveMQQueue("TEST");
|
||||
|
||||
connection.start();
|
||||
|
||||
TextMessage[] outbound = new TextMessage[]{session.createTextMessage("First Message"),
|
||||
session.createTextMessage("Second Message"),
|
||||
session.createTextMessage("Third Message")};
|
||||
|
||||
// create consumer
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
// lets consume any outstanding messages from previous test runs
|
||||
while (consumer.receive(1000) != null) {
|
||||
}
|
||||
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.send(outbound[0]);
|
||||
producer.send(outbound[1]);
|
||||
producer.send(outbound[2]);
|
||||
|
||||
// create browser first
|
||||
QueueBrowser browser = session.createBrowser(destination);
|
||||
Enumeration<?> enumeration = browser.getEnumeration();
|
||||
|
||||
// browse some messages
|
||||
assertEquals(outbound[0], enumeration.nextElement());
|
||||
assertEquals(outbound[1], enumeration.nextElement());
|
||||
//assertEquals(outbound[2], (Message) enumeration.nextElement());
|
||||
|
||||
browser.close();
|
||||
|
||||
// Receive the first message.
|
||||
TextMessage msg = (TextMessage)consumer.receive(1000);
|
||||
assertEquals("Expected " + outbound[0].getText() + " but received " + msg.getText(), outbound[0], msg);
|
||||
msg = (TextMessage)consumer.receive(1000);
|
||||
assertEquals("Expected " + outbound[1].getText() + " but received " + msg.getText(), outbound[1], msg);
|
||||
msg = (TextMessage)consumer.receive(1000);
|
||||
assertEquals("Expected " + outbound[2].getText() + " but received " + msg.getText(), outbound[2], msg);
|
||||
|
||||
consumer.close();
|
||||
producer.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService brokerService = super.createBroker();
|
||||
PolicyMap policyMap = new PolicyMap();
|
||||
PolicyEntry policyEntry = new PolicyEntry();
|
||||
policyEntry.setUseCache(isUseCache);
|
||||
policyEntry.setMaxBrowsePageSize(4096);
|
||||
policyMap.setDefaultEntry(policyEntry);
|
||||
brokerService.setDestinationPolicy(policyMap);
|
||||
return brokerService;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/**
|
||||
* 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.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.Topic;
|
||||
|
||||
import org.apache.activemq.broker.BrokerRegistry;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.region.Queue;
|
||||
import org.apache.activemq.broker.region.RegionBroker;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.test.JmsTopicSendReceiveTest;
|
||||
import org.apache.activemq.util.Wait;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsQueueCompositeSendReceiveTest extends JmsTopicSendReceiveTest {
|
||||
private static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory
|
||||
.getLog(JmsQueueCompositeSendReceiveTest.class);
|
||||
|
||||
/**
|
||||
* Sets a test to have a queue destination and non-persistent delivery mode.
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
topic = false;
|
||||
deliveryMode = DeliveryMode.NON_PERSISTENT;
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the consumer subject.
|
||||
*
|
||||
* @return String - consumer subject
|
||||
* @see org.apache.activemq.test.TestSupport#getConsumerSubject()
|
||||
*/
|
||||
protected String getConsumerSubject() {
|
||||
return "FOO.BAR.HUMBUG";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the producer subject.
|
||||
*
|
||||
* @return String - producer subject
|
||||
* @see org.apache.activemq.test.TestSupport#getProducerSubject()
|
||||
*/
|
||||
protected String getProducerSubject() {
|
||||
return "FOO.BAR.HUMBUG,FOO.BAR.HUMBUG2";
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if all the messages sent are being received.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSendReceive() throws Exception {
|
||||
super.testSendReceive();
|
||||
messages.clear();
|
||||
Destination consumerDestination = consumeSession.createQueue("FOO.BAR.HUMBUG2");
|
||||
LOG.info("Created consumer destination: " + consumerDestination + " of type: " + consumerDestination.getClass());
|
||||
MessageConsumer consumer = null;
|
||||
if (durable) {
|
||||
LOG.info("Creating durable consumer");
|
||||
consumer = consumeSession.createDurableSubscriber((Topic) consumerDestination, getName());
|
||||
} else {
|
||||
consumer = consumeSession.createConsumer(consumerDestination);
|
||||
}
|
||||
consumer.setMessageListener(this);
|
||||
|
||||
assertMessagesAreReceived();
|
||||
LOG.info("" + data.length + " messages(s) received, closing down connections");
|
||||
}
|
||||
|
||||
public void testDuplicate() throws Exception {
|
||||
ActiveMQDestination queue = (ActiveMQDestination)session.createQueue("TEST,TEST");
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
Message message = createMessage(i);
|
||||
configureMessage(message);
|
||||
if (verbose) {
|
||||
LOG.info("About to send a message: " + message + " with text: " + data[i]);
|
||||
}
|
||||
producer.send(queue, message);
|
||||
}
|
||||
|
||||
Thread.sleep(200); // wait for messages to be queued
|
||||
|
||||
BrokerService broker = BrokerRegistry.getInstance().lookup("localhost");
|
||||
final Queue dest = (Queue)((RegionBroker)broker.getRegionBroker()).getQueueRegion().getDestinationMap().get(new ActiveMQQueue("TEST"));
|
||||
assertTrue("all messages were received", Wait.waitFor(new Wait.Condition(){
|
||||
public boolean isSatisified() throws Exception {
|
||||
return data.length == dest.getDestinationStatistics().getMessages().getCount();
|
||||
}}));
|
||||
|
||||
dest.purge();
|
||||
assertEquals(0, dest.getDestinationStatistics().getMessages().getCount());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsQueueRequestReplyTest extends JmsTopicRequestReplyTest {
|
||||
|
||||
/**
|
||||
* Set up the test with a queue.
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
topic = false;
|
||||
super.setUp();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsQueueSelectorTest extends JmsTopicSelectorTest {
|
||||
public void setUp() throws Exception {
|
||||
topic = false;
|
||||
super.setUp();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* 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 org.apache.activemq.test.JmsTopicSendReceiveTest;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsQueueSendReceiveTest extends JmsTopicSendReceiveTest {
|
||||
|
||||
/**
|
||||
* Set up the test with a queue.
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
topic = false;
|
||||
super.setUp();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* 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.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsQueueSendReceiveTwoConnectionsStartBeforeBrokerTest extends JmsQueueSendReceiveTwoConnectionsTest {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JmsQueueSendReceiveTwoConnectionsStartBeforeBrokerTest.class);
|
||||
|
||||
private Queue<Exception> errors = new ConcurrentLinkedQueue<Exception>();
|
||||
private int delayBeforeStartingBroker = 1000;
|
||||
private BrokerService broker;
|
||||
|
||||
public void startBroker() {
|
||||
// Initialize the broker
|
||||
LOG.info("Lets wait: " + delayBeforeStartingBroker + " millis before creating the broker");
|
||||
try {
|
||||
Thread.sleep(delayBeforeStartingBroker);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
LOG.info("Now starting the broker");
|
||||
try {
|
||||
broker = new BrokerService();
|
||||
broker.setPersistent(false);
|
||||
broker.addConnector("tcp://localhost:61616");
|
||||
broker.start();
|
||||
} catch (Exception e) {
|
||||
LOG.info("Caught: " + e);
|
||||
errors.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory("failover:(tcp://localhost:61616)?maxReconnectAttempts=10&useExponentialBackOff=false&initialReconnectDelay=200");
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
setAutoFail(true);
|
||||
// now lets asynchronously start a broker
|
||||
Thread thread = new Thread() {
|
||||
public void run() {
|
||||
startBroker();
|
||||
}
|
||||
};
|
||||
thread.start();
|
||||
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
}
|
||||
if (!errors.isEmpty()) {
|
||||
Exception e = errors.remove();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* 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 org.apache.activemq.test.JmsTopicSendReceiveWithTwoConnectionsTest;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsQueueSendReceiveTwoConnectionsTest extends JmsTopicSendReceiveWithTwoConnectionsTest {
|
||||
|
||||
/**
|
||||
* Set up the test with a queue and using two connections.
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
topic = false;
|
||||
super.setUp();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsQueueSendReceiveUsingTwoSessionsTest extends JmsQueueSendReceiveTest {
|
||||
|
||||
/**
|
||||
* Set up the test using two sessions.
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
useSeparateSession = true;
|
||||
super.setUp();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* 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.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.Topic;
|
||||
|
||||
import org.apache.activemq.test.JmsTopicSendReceiveTest;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsQueueTopicCompositeSendReceiveTest extends JmsTopicSendReceiveTest {
|
||||
private static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory
|
||||
.getLog(JmsQueueTopicCompositeSendReceiveTest.class);
|
||||
Destination consumerDestination2;
|
||||
MessageConsumer consumer2;
|
||||
|
||||
/**
|
||||
* Sets a test to have a queue destination and non-persistent delivery mode.
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
deliveryMode = DeliveryMode.NON_PERSISTENT;
|
||||
topic = false;
|
||||
super.setUp();
|
||||
consumerDestination2 = consumeSession.createTopic("FOO.BAR.HUMBUG2");
|
||||
LOG.info("Created consumer destination: " + consumerDestination2 + " of type: " + consumerDestination2.getClass());
|
||||
if (durable) {
|
||||
LOG.info("Creating durable consumer");
|
||||
consumer2 = consumeSession.createDurableSubscriber((Topic) consumerDestination2, getName());
|
||||
} else {
|
||||
consumer2 = consumeSession.createConsumer(consumerDestination2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the consumer subject.
|
||||
*
|
||||
* @return String - consumer subject
|
||||
* @see org.apache.activemq.test.TestSupport#getConsumerSubject()
|
||||
*/
|
||||
protected String getConsumerSubject() {
|
||||
return "FOO.BAR.HUMBUG";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the producer subject.
|
||||
*
|
||||
* @return String - producer subject
|
||||
* @see org.apache.activemq.test.TestSupport#getProducerSubject()
|
||||
*/
|
||||
protected String getProducerSubject() {
|
||||
return "queue://FOO.BAR.HUMBUG,topic://FOO.BAR.HUMBUG2";
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if all the messages sent are being received.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSendReceive() throws Exception {
|
||||
super.testSendReceive();
|
||||
messages.clear();
|
||||
consumer2.setMessageListener(this);
|
||||
assertMessagesAreReceived();
|
||||
LOG.info("" + data.length + " messages(s) received, closing down connections");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
/**
|
||||
* 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.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.test.JmsTopicSendReceiveTest;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsQueueWildcardSendReceiveTest extends JmsTopicSendReceiveTest {
|
||||
|
||||
private String destination1String = "TEST.ONE.ONE";
|
||||
private String destination2String = "TEST.ONE.ONE.ONE";
|
||||
private String destination3String = "TEST.ONE.TWO";
|
||||
private String destination4String = "TEST.TWO.ONE";
|
||||
|
||||
/**
|
||||
* Sets a test to have a queue destination and non-persistent delivery mode.
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
topic = false;
|
||||
deliveryMode = DeliveryMode.NON_PERSISTENT;
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the consumer subject.
|
||||
*
|
||||
* @return String - consumer subject
|
||||
* @see org.apache.activemq.test.TestSupport#getConsumerSubject()
|
||||
*/
|
||||
protected String getConsumerSubject() {
|
||||
return "FOO.>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the producer subject.
|
||||
*
|
||||
* @return String - producer subject
|
||||
* @see org.apache.activemq.test.TestSupport#getProducerSubject()
|
||||
*/
|
||||
protected String getProducerSubject() {
|
||||
return "FOO.BAR.HUMBUG";
|
||||
}
|
||||
|
||||
public void testReceiveWildcardQueueEndAsterisk() throws Exception {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
ActiveMQDestination destination1 = (ActiveMQDestination)session.createQueue(destination1String);
|
||||
ActiveMQDestination destination3 = (ActiveMQDestination)session.createQueue(destination3String);
|
||||
|
||||
Message m = null;
|
||||
MessageConsumer consumer = null;
|
||||
String text = null;
|
||||
|
||||
sendMessage(session, destination1, destination1String);
|
||||
sendMessage(session, destination3, destination3String);
|
||||
ActiveMQDestination destination6 = (ActiveMQDestination)session.createQueue("TEST.ONE.*");
|
||||
consumer = session.createConsumer(destination6);
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
text = ((TextMessage)m).getText();
|
||||
if (!(text.equals(destination1String) || text.equals(destination3String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
text = ((TextMessage)m).getText();
|
||||
if (!(text.equals(destination1String) || text.equals(destination3String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void testReceiveWildcardQueueEndGreaterThan() throws Exception {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
ActiveMQDestination destination1 = (ActiveMQDestination)session.createQueue(destination1String);
|
||||
ActiveMQDestination destination2 = (ActiveMQDestination)session.createQueue(destination2String);
|
||||
ActiveMQDestination destination3 = (ActiveMQDestination)session.createQueue(destination3String);
|
||||
|
||||
Message m = null;
|
||||
MessageConsumer consumer = null;
|
||||
String text = null;
|
||||
|
||||
sendMessage(session, destination1, destination1String);
|
||||
sendMessage(session, destination2, destination2String);
|
||||
sendMessage(session, destination3, destination3String);
|
||||
ActiveMQDestination destination7 = (ActiveMQDestination)session.createQueue("TEST.ONE.>");
|
||||
consumer = session.createConsumer(destination7);
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
text = ((TextMessage)m).getText();
|
||||
if (!(text.equals(destination1String) || text.equals(destination2String) || text.equals(destination3String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
if (!(text.equals(destination1String) || text.equals(destination2String) || text.equals(destination3String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
if (!(text.equals(destination1String) || text.equals(destination2String) || text.equals(destination3String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void testReceiveWildcardQueueMidAsterisk() throws Exception {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
ActiveMQDestination destination1 = (ActiveMQDestination)session.createQueue(destination1String);
|
||||
ActiveMQDestination destination4 = (ActiveMQDestination)session.createQueue(destination4String);
|
||||
|
||||
Message m = null;
|
||||
MessageConsumer consumer = null;
|
||||
String text = null;
|
||||
|
||||
sendMessage(session, destination1, destination1String);
|
||||
sendMessage(session, destination4, destination4String);
|
||||
ActiveMQDestination destination8 = (ActiveMQDestination)session.createQueue("TEST.*.ONE");
|
||||
consumer = session.createConsumer(destination8);
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
text = ((TextMessage)m).getText();
|
||||
if (!(text.equals(destination1String) || text.equals(destination4String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
text = ((TextMessage)m).getText();
|
||||
if (!(text.equals(destination1String) || text.equals(destination4String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
assertNull(consumer.receiveNoWait());
|
||||
|
||||
}
|
||||
|
||||
private void sendMessage(Session session, Destination destination, String text) throws JMSException {
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.send(session.createTextMessage(text));
|
||||
producer.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,562 @@
|
|||
/**
|
||||
* 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.concurrent.TimeUnit;
|
||||
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.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.jms.Topic;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
import org.apache.activemq.transport.vm.VMTransport;
|
||||
import org.apache.activemq.util.Wait;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsRedeliveredTest extends TestCase {
|
||||
|
||||
private Connection connection;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
connection = createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a connection.
|
||||
*
|
||||
* @return connection
|
||||
* @throws Exception
|
||||
*/
|
||||
protected Connection createConnection() throws Exception {
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(
|
||||
"vm://localhost?broker.persistent=false");
|
||||
return factory.createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a message unacknowledged message gets to be resent when the
|
||||
* session is closed and then a new consumer session is created.
|
||||
*
|
||||
*/
|
||||
public void testQueueSessionCloseMarksMessageRedelivered() throws JMSException {
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue("queue-" + getName());
|
||||
MessageProducer producer = createProducer(session, queue);
|
||||
producer.send(createTextMessage(session));
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertFalse("Message should not be redelivered.", msg.getJMSRedelivered());
|
||||
// Don't ack the message.
|
||||
|
||||
// Reset the session. This should cause the Unacked message to be
|
||||
// redelivered.
|
||||
session.close();
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
|
||||
// Attempt to Consume the message...
|
||||
consumer = session.createConsumer(queue);
|
||||
msg = consumer.receive(2000);
|
||||
assertNotNull(msg);
|
||||
assertTrue("Message should be redelivered.", msg.getJMSRedelivered());
|
||||
msg.acknowledge();
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void testQueueSessionCloseMarksUnAckedMessageRedelivered() throws JMSException {
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue("queue-" + getName());
|
||||
MessageProducer producer = createProducer(session, queue);
|
||||
producer.send(createTextMessage(session, "1"));
|
||||
producer.send(createTextMessage(session, "2"));
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertFalse("Message should not be redelivered.", msg.getJMSRedelivered());
|
||||
assertEquals("1", ((TextMessage)msg).getText());
|
||||
msg.acknowledge();
|
||||
|
||||
// Don't ack the message.
|
||||
msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertFalse("Message should not be redelivered.", msg.getJMSRedelivered());
|
||||
assertEquals("2", ((TextMessage)msg).getText());
|
||||
|
||||
// Reset the session. This should cause the Unacked message to be
|
||||
// redelivered.
|
||||
session.close();
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
|
||||
// Attempt to Consume the message...
|
||||
consumer = session.createConsumer(queue);
|
||||
msg = consumer.receive(2000);
|
||||
assertNotNull(msg);
|
||||
assertEquals("2", ((TextMessage)msg).getText());
|
||||
assertTrue("Message should be redelivered.", msg.getJMSRedelivered());
|
||||
msg.acknowledge();
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests session recovery and that the redelivered message is marked as
|
||||
* such. Session uses client acknowledgement, the destination is a queue.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testQueueRecoverMarksMessageRedelivered() throws JMSException {
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue("queue-" + getName());
|
||||
MessageProducer producer = createProducer(session, queue);
|
||||
producer.send(createTextMessage(session));
|
||||
|
||||
// Consume the message...
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertFalse("Message should not be redelivered.", msg.getJMSRedelivered());
|
||||
// Don't ack the message.
|
||||
|
||||
// Reset the session. This should cause the Unacked message to be
|
||||
// redelivered.
|
||||
session.recover();
|
||||
|
||||
// Attempt to Consume the message...
|
||||
msg = consumer.receive(2000);
|
||||
assertNotNull(msg);
|
||||
assertTrue("Message should be redelivered.", msg.getJMSRedelivered());
|
||||
msg.acknowledge();
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rollback message to be marked as redelivered. Session uses client
|
||||
* acknowledgement and the destination is a queue.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testQueueRollbackMarksMessageRedelivered() throws JMSException {
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue("queue-" + getName());
|
||||
MessageProducer producer = createProducer(session, queue);
|
||||
producer.send(createTextMessage(session));
|
||||
session.commit();
|
||||
|
||||
// Get the message... Should not be redelivered.
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertFalse("Message should not be redelivered.", msg.getJMSRedelivered());
|
||||
|
||||
// Rollback.. should cause redelivery.
|
||||
session.rollback();
|
||||
|
||||
// Attempt to Consume the message...
|
||||
msg = consumer.receive(2000);
|
||||
assertNotNull(msg);
|
||||
assertTrue("Message should be redelivered.", msg.getJMSRedelivered());
|
||||
|
||||
session.commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the message gets to be re-delivered when the session closes and
|
||||
* that the re-delivered message is marked as such. Session uses client
|
||||
* acknowledgment, the destination is a topic and the consumer is a durable
|
||||
* subscriber.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testDurableTopicSessionCloseMarksMessageRedelivered() throws JMSException {
|
||||
connection.setClientID(getName());
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Topic topic = session.createTopic("topic-" + getName());
|
||||
MessageConsumer consumer = session.createDurableSubscriber(topic, "sub1");
|
||||
|
||||
// This case only works with persistent messages since transient
|
||||
// messages
|
||||
// are dropped when the consumer goes offline.
|
||||
MessageProducer producer = session.createProducer(topic);
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
producer.send(createTextMessage(session));
|
||||
|
||||
// Consume the message...
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertFalse("Message should not be re-delivered.", msg.getJMSRedelivered());
|
||||
// Don't ack the message.
|
||||
|
||||
// Reset the session. This should cause the Unacked message to be
|
||||
// re-delivered.
|
||||
session.close();
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
|
||||
// Attempt to Consume the message...
|
||||
consumer = session.createDurableSubscriber(topic, "sub1");
|
||||
msg = consumer.receive(2000);
|
||||
assertNotNull(msg);
|
||||
assertTrue("Message should be redelivered.", msg.getJMSRedelivered());
|
||||
msg.acknowledge();
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests session recovery and that the redelivered message is marked as
|
||||
* such. Session uses client acknowledgement, the destination is a topic and
|
||||
* the consumer is a durable suscriber.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testDurableTopicRecoverMarksMessageRedelivered() throws JMSException {
|
||||
connection.setClientID(getName());
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Topic topic = session.createTopic("topic-" + getName());
|
||||
MessageConsumer consumer = session.createDurableSubscriber(topic, "sub1");
|
||||
|
||||
MessageProducer producer = createProducer(session, topic);
|
||||
producer.send(createTextMessage(session));
|
||||
|
||||
// Consume the message...
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertFalse("Message should not be redelivered.", msg.getJMSRedelivered());
|
||||
// Don't ack the message.
|
||||
|
||||
// Reset the session. This should cause the Unacked message to be
|
||||
// redelivered.
|
||||
session.recover();
|
||||
|
||||
// Attempt to Consume the message...
|
||||
msg = consumer.receive(2000);
|
||||
assertNotNull(msg);
|
||||
assertTrue("Message should be redelivered.", msg.getJMSRedelivered());
|
||||
msg.acknowledge();
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rollback message to be marked as redelivered. Session uses client
|
||||
* acknowledgement and the destination is a topic.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testDurableTopicRollbackMarksMessageRedelivered() throws JMSException {
|
||||
connection.setClientID(getName());
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
|
||||
Topic topic = session.createTopic("topic-" + getName());
|
||||
MessageConsumer consumer = session.createDurableSubscriber(topic, "sub1");
|
||||
|
||||
MessageProducer producer = createProducer(session, topic);
|
||||
producer.send(createTextMessage(session));
|
||||
session.commit();
|
||||
|
||||
// Get the message... Should not be redelivered.
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertFalse("Message should not be redelivered.", msg.getJMSRedelivered());
|
||||
|
||||
// Rollback.. should cause redelivery.
|
||||
session.rollback();
|
||||
|
||||
// Attempt to Consume the message...
|
||||
msg = consumer.receive(2000);
|
||||
assertNotNull(msg);
|
||||
assertTrue("Message should be redelivered.", msg.getJMSRedelivered());
|
||||
|
||||
session.commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testTopicRecoverMarksMessageRedelivered() throws JMSException {
|
||||
|
||||
connection.setClientID(getName());
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Topic topic = session.createTopic("topic-" + getName());
|
||||
MessageConsumer consumer = session.createConsumer(topic);
|
||||
|
||||
MessageProducer producer = createProducer(session, topic);
|
||||
producer.send(createTextMessage(session));
|
||||
|
||||
// Consume the message...
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertFalse("Message should not be redelivered.", msg.getJMSRedelivered());
|
||||
// Don't ack the message.
|
||||
|
||||
// Reset the session. This should cause the Unacked message to be
|
||||
// redelivered.
|
||||
session.recover();
|
||||
|
||||
// Attempt to Consume the message...
|
||||
msg = consumer.receive(2000);
|
||||
assertNotNull(msg);
|
||||
assertTrue("Message should be redelivered.", msg.getJMSRedelivered());
|
||||
msg.acknowledge();
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests rollback message to be marked as redelivered. Session uses client
|
||||
* acknowledgement and the destination is a topic.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testTopicRollbackMarksMessageRedelivered() throws JMSException {
|
||||
connection.setClientID(getName());
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
|
||||
Topic topic = session.createTopic("topic-" + getName());
|
||||
MessageConsumer consumer = session.createConsumer(topic);
|
||||
|
||||
MessageProducer producer = createProducer(session, topic);
|
||||
producer.send(createTextMessage(session));
|
||||
session.commit();
|
||||
|
||||
// Get the message... Should not be redelivered.
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertFalse("Message should not be redelivered.", msg.getJMSRedelivered());
|
||||
|
||||
// Rollback.. should cause redelivery.
|
||||
session.rollback();
|
||||
|
||||
// Attempt to Consume the message...
|
||||
msg = consumer.receive(2000);
|
||||
assertNotNull(msg);
|
||||
assertTrue("Message should be redelivered.", msg.getJMSRedelivered());
|
||||
|
||||
session.commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
public void testNoReceiveConsumerDisconnectDoesNotIncrementRedelivery() throws Exception {
|
||||
connection.setClientID(getName());
|
||||
connection.start();
|
||||
|
||||
Connection keepBrokerAliveConnection = createConnection();
|
||||
keepBrokerAliveConnection.start();
|
||||
|
||||
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue("queue-" + getName());
|
||||
final MessageConsumer consumer = session.createConsumer(queue);
|
||||
|
||||
MessageProducer producer = createProducer(session, queue);
|
||||
producer.send(createTextMessage(session));
|
||||
session.commit();
|
||||
|
||||
Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return ((ActiveMQMessageConsumer)consumer).getMessageSize() == 1;
|
||||
}
|
||||
});
|
||||
|
||||
// whack the connection - like a rebalance or tcp drop
|
||||
((ActiveMQConnection)connection).getTransport().narrow(VMTransport.class).stop();
|
||||
|
||||
session = keepBrokerAliveConnection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
|
||||
MessageConsumer messageConsumer = session.createConsumer(queue);
|
||||
Message msg = messageConsumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
msg.acknowledge();
|
||||
|
||||
assertFalse("Message should not be redelivered.", msg.getJMSRedelivered());
|
||||
session.close();
|
||||
keepBrokerAliveConnection.close();
|
||||
}
|
||||
|
||||
public void testNoReceiveConsumerDoesNotIncrementRedelivery() throws Exception {
|
||||
connection.setClientID(getName());
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue("queue-" + getName());
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
|
||||
MessageProducer producer = createProducer(session, queue);
|
||||
producer.send(createTextMessage(session));
|
||||
session.commit();
|
||||
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
consumer.close();
|
||||
|
||||
consumer = session.createConsumer(queue);
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
|
||||
assertFalse("Message should not be redelivered.", msg.getJMSRedelivered());
|
||||
session.close();
|
||||
}
|
||||
|
||||
public void testNoReceiveDurableConsumerDoesNotIncrementRedelivery() throws Exception {
|
||||
connection.setClientID(getName());
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
|
||||
Topic topic = session.createTopic("topic-" + getName());
|
||||
MessageConsumer consumer = session.createDurableSubscriber(topic, "sub");
|
||||
|
||||
MessageProducer producer = createProducer(session, topic);
|
||||
producer.send(createTextMessage(session));
|
||||
session.commit();
|
||||
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
consumer.close();
|
||||
|
||||
consumer = session.createDurableSubscriber(topic, "sub");
|
||||
Message msg = consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
|
||||
assertFalse("Message should not be redelivered.", msg.getJMSRedelivered());
|
||||
session.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a text message.
|
||||
*
|
||||
* @param session
|
||||
* @return TextMessage.
|
||||
* @throws JMSException
|
||||
*/
|
||||
private TextMessage createTextMessage(Session session) throws JMSException {
|
||||
return createTextMessage(session, "Hello");
|
||||
}
|
||||
|
||||
private TextMessage createTextMessage(Session session, String txt) throws JMSException {
|
||||
return session.createTextMessage(txt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a producer.
|
||||
*
|
||||
* @param session
|
||||
* @param queue - destination.
|
||||
* @return MessageProducer
|
||||
* @throws JMSException
|
||||
*/
|
||||
private MessageProducer createProducer(Session session, Destination queue) throws JMSException {
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.setDeliveryMode(getDeliveryMode());
|
||||
return producer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns delivery mode.
|
||||
*
|
||||
* @return int - persistent delivery mode.
|
||||
*/
|
||||
protected int getDeliveryMode() {
|
||||
return DeliveryMode.PERSISTENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the JmsRedeliverTest with the delivery mode set as persistent.
|
||||
*/
|
||||
public static final class PersistentCase extends JmsRedeliveredTest {
|
||||
|
||||
/**
|
||||
* Returns delivery mode.
|
||||
*
|
||||
* @return int - persistent delivery mode.
|
||||
*/
|
||||
protected int getDeliveryMode() {
|
||||
return DeliveryMode.PERSISTENT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the JmsRedeliverTest with the delivery mode set as non-persistent.
|
||||
*/
|
||||
public static final class TransientCase extends JmsRedeliveredTest {
|
||||
|
||||
/**
|
||||
* Returns delivery mode.
|
||||
*
|
||||
* @return int - non-persistent delivery mode.
|
||||
*/
|
||||
protected int getDeliveryMode() {
|
||||
return DeliveryMode.NON_PERSISTENT;
|
||||
}
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite();
|
||||
suite.addTestSuite(PersistentCase.class);
|
||||
suite.addTestSuite(TransientCase.class);
|
||||
return suite;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,358 @@
|
|||
/**
|
||||
* 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.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.jms.Connection;
|
||||
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 org.apache.activemq.broker.BrokerService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TestName;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class JmsRollbackRedeliveryTest {
|
||||
@Rule
|
||||
public TestName testName = new TestName();
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(JmsRollbackRedeliveryTest.class);
|
||||
final int nbMessages = 10;
|
||||
final String destinationName = "Destination";
|
||||
final String brokerUrl = "vm://localhost?create=false";
|
||||
boolean consumerClose = true;
|
||||
boolean rollback = true;
|
||||
BrokerService broker;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
LOG.debug("Starting " + testName.getMethodName());
|
||||
broker = new BrokerService();
|
||||
broker.setPersistent(false);
|
||||
broker.setUseJmx(false);
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
}
|
||||
LOG.debug("Finishing " + testName.getMethodName());
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRedelivery() throws Exception {
|
||||
doTestRedelivery(brokerUrl, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRedeliveryWithInterleavedProducer() throws Exception {
|
||||
doTestRedelivery(brokerUrl, true);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRedeliveryWithPrefetch0() throws Exception {
|
||||
doTestRedelivery(brokerUrl + "?jms.prefetchPolicy.queuePrefetch=0", true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRedeliveryWithPrefetch1() throws Exception {
|
||||
doTestRedelivery(brokerUrl + "?jms.prefetchPolicy.queuePrefetch=1", true);
|
||||
}
|
||||
|
||||
public void doTestRedelivery(String brokerUrl, boolean interleaveProducer) throws Exception {
|
||||
LOG.debug("entering doTestRedelivery interleaveProducer is " + interleaveProducer);
|
||||
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerUrl);
|
||||
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
|
||||
if (interleaveProducer) {
|
||||
populateDestinationWithInterleavedProducer(nbMessages, destinationName, connection);
|
||||
} else {
|
||||
populateDestination(nbMessages, destinationName, connection);
|
||||
}
|
||||
|
||||
// Consume messages and rollback transactions
|
||||
{
|
||||
AtomicInteger received = new AtomicInteger();
|
||||
Map<String, Boolean> rolledback = new ConcurrentHashMap<String, Boolean>();
|
||||
while (received.get() < nbMessages) {
|
||||
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination = session.createQueue(destinationName);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
TextMessage msg = (TextMessage) consumer.receive(6000000);
|
||||
if (msg != null) {
|
||||
if (msg != null && rolledback.put(msg.getText(), Boolean.TRUE) != null) {
|
||||
LOG.info("Received message " + msg.getText() + " (" + received.getAndIncrement() + ")" + msg.getJMSMessageID());
|
||||
assertTrue(msg.getJMSRedelivered());
|
||||
assertEquals(2, msg.getLongProperty("JMSXDeliveryCount"));
|
||||
session.commit();
|
||||
} else {
|
||||
LOG.info("Rollback message " + msg.getText() + " id: " + msg.getJMSMessageID());
|
||||
assertFalse("should not have redelivery flag set, id: " + msg.getJMSMessageID(), msg.getJMSRedelivered());
|
||||
session.rollback();
|
||||
}
|
||||
}
|
||||
consumer.close();
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRedeliveryOnSingleConsumer() throws Exception {
|
||||
|
||||
ConnectionFactory connectionFactory =
|
||||
new ActiveMQConnectionFactory(brokerUrl);
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
|
||||
populateDestinationWithInterleavedProducer(nbMessages, destinationName, connection);
|
||||
|
||||
// Consume messages and rollback transactions
|
||||
{
|
||||
AtomicInteger received = new AtomicInteger();
|
||||
Map<String, Boolean> rolledback = new ConcurrentHashMap<String, Boolean>();
|
||||
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination = session.createQueue(destinationName);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
while (received.get() < nbMessages) {
|
||||
TextMessage msg = (TextMessage) consumer.receive(6000000);
|
||||
if (msg != null) {
|
||||
if (msg != null && rolledback.put(msg.getText(), Boolean.TRUE) != null) {
|
||||
LOG.info("Received message " + msg.getText() + " (" + received.getAndIncrement() + ")" + msg.getJMSMessageID());
|
||||
assertTrue(msg.getJMSRedelivered());
|
||||
session.commit();
|
||||
} else {
|
||||
LOG.info("Rollback message " + msg.getText() + " id: " + msg.getJMSMessageID());
|
||||
session.rollback();
|
||||
}
|
||||
}
|
||||
}
|
||||
consumer.close();
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRedeliveryOnSingleSession() throws Exception {
|
||||
|
||||
ConnectionFactory connectionFactory =
|
||||
new ActiveMQConnectionFactory(brokerUrl);
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
|
||||
populateDestination(nbMessages, destinationName, connection);
|
||||
|
||||
// Consume messages and rollback transactions
|
||||
{
|
||||
AtomicInteger received = new AtomicInteger();
|
||||
Map<String, Boolean> rolledback = new ConcurrentHashMap<String, Boolean>();
|
||||
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination = session.createQueue(destinationName);
|
||||
while (received.get() < nbMessages) {
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
TextMessage msg = (TextMessage) consumer.receive(6000000);
|
||||
if (msg != null) {
|
||||
if (msg != null && rolledback.put(msg.getText(), Boolean.TRUE) != null) {
|
||||
LOG.info("Received message " + msg.getText() + " (" + received.getAndIncrement() + ")" + msg.getJMSMessageID());
|
||||
assertTrue(msg.getJMSRedelivered());
|
||||
session.commit();
|
||||
} else {
|
||||
LOG.info("Rollback message " + msg.getText() + " id: " + msg.getJMSMessageID());
|
||||
session.rollback();
|
||||
}
|
||||
}
|
||||
consumer.close();
|
||||
}
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
|
||||
// AMQ-1593
|
||||
@Test
|
||||
public void testValidateRedeliveryCountOnRollback() throws Exception {
|
||||
|
||||
final int numMessages = 1;
|
||||
ConnectionFactory connectionFactory =
|
||||
new ActiveMQConnectionFactory(brokerUrl);
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
|
||||
populateDestination(numMessages, destinationName, connection);
|
||||
|
||||
{
|
||||
AtomicInteger received = new AtomicInteger();
|
||||
final int maxRetries = new RedeliveryPolicy().getMaximumRedeliveries();
|
||||
while (received.get() < maxRetries) {
|
||||
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
Destination destination = session.createQueue(destinationName);
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
TextMessage msg = (TextMessage) consumer.receive(1000);
|
||||
if (msg != null) {
|
||||
LOG.info("Received message " + msg.getText() + " (" + received.getAndIncrement() + ")" + msg.getJMSMessageID());
|
||||
assertEquals("redelivery property matches deliveries", received.get(), msg.getLongProperty("JMSXDeliveryCount"));
|
||||
session.rollback();
|
||||
}
|
||||
session.close();
|
||||
}
|
||||
consumeMessage(connection, maxRetries + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// AMQ-1593
|
||||
@Test
|
||||
public void testValidateRedeliveryCountOnRollbackWithPrefetch0() throws Exception {
|
||||
|
||||
final int numMessages = 1;
|
||||
ConnectionFactory connectionFactory =
|
||||
new ActiveMQConnectionFactory(brokerUrl + "?jms.prefetchPolicy.queuePrefetch=0");
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
|
||||
populateDestination(numMessages, destinationName, connection);
|
||||
|
||||
{
|
||||
AtomicInteger received = new AtomicInteger();
|
||||
final int maxRetries = new RedeliveryPolicy().getMaximumRedeliveries();
|
||||
while (received.get() < maxRetries) {
|
||||
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
Destination destination = session.createQueue(destinationName);
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
TextMessage msg = (TextMessage) consumer.receive(1000);
|
||||
if (msg != null) {
|
||||
LOG.info("Received message " + msg.getText() + " (" + received.getAndIncrement() + ")" + msg.getJMSMessageID());
|
||||
assertEquals("redelivery property matches deliveries", received.get(), msg.getLongProperty("JMSXDeliveryCount"));
|
||||
session.rollback();
|
||||
}
|
||||
session.close();
|
||||
}
|
||||
|
||||
consumeMessage(connection, maxRetries + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void consumeMessage(Connection connection, final int deliveryCount)
|
||||
throws JMSException {
|
||||
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
Destination destination = session.createQueue(destinationName);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
TextMessage msg = (TextMessage) consumer.receive(1000);
|
||||
assertNotNull(msg);
|
||||
assertEquals("redelivery property matches deliveries", deliveryCount, msg.getLongProperty("JMSXDeliveryCount"));
|
||||
session.commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRedeliveryPropertyWithNoRollback() throws Exception {
|
||||
final int numMessages = 1;
|
||||
ConnectionFactory connectionFactory =
|
||||
new ActiveMQConnectionFactory(brokerUrl);
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
|
||||
populateDestination(numMessages, destinationName, connection);
|
||||
connection.close();
|
||||
|
||||
{
|
||||
AtomicInteger received = new AtomicInteger();
|
||||
final int maxRetries = new RedeliveryPolicy().getMaximumRedeliveries();
|
||||
while (received.get() < maxRetries) {
|
||||
connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
Destination destination = session.createQueue(destinationName);
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
TextMessage msg = (TextMessage) consumer.receive(2000);
|
||||
if (msg != null) {
|
||||
LOG.info("Received message " + msg.getText() + " (" + received.getAndIncrement() + ")" + msg.getJMSMessageID());
|
||||
assertEquals("redelivery property matches deliveries", received.get(), msg.getLongProperty("JMSXDeliveryCount"));
|
||||
}
|
||||
session.close();
|
||||
connection.close();
|
||||
}
|
||||
connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
consumeMessage(connection, maxRetries + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void populateDestination(final int nbMessages,
|
||||
final String destinationName, Connection connection)
|
||||
throws JMSException {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination = session.createQueue(destinationName);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
for (int i = 1; i <= nbMessages; i++) {
|
||||
producer.send(session.createTextMessage("<hello id='" + i + "'/>"));
|
||||
}
|
||||
producer.close();
|
||||
session.close();
|
||||
}
|
||||
|
||||
|
||||
private void populateDestinationWithInterleavedProducer(final int nbMessages,
|
||||
final String destinationName, Connection connection)
|
||||
throws JMSException {
|
||||
Session session1 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination1 = session1.createQueue(destinationName);
|
||||
MessageProducer producer1 = session1.createProducer(destination1);
|
||||
Session session2 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination2 = session2.createQueue(destinationName);
|
||||
MessageProducer producer2 = session2.createProducer(destination2);
|
||||
|
||||
for (int i = 1; i <= nbMessages; i++) {
|
||||
if (i%2 == 0) {
|
||||
producer1.send(session1.createTextMessage("<hello id='" + i + "'/>"));
|
||||
} else {
|
||||
producer2.send(session2.createTextMessage("<hello id='" + i + "'/>"));
|
||||
}
|
||||
}
|
||||
producer1.close();
|
||||
session1.close();
|
||||
producer2.close();
|
||||
session2.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
/**
|
||||
* 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.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.jms.DeliveryMode;
|
||||
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.TextMessage;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsSendReceiveTestSupport extends TestSupport implements MessageListener {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JmsSendReceiveTestSupport.class);
|
||||
|
||||
protected int messageCount = 100;
|
||||
protected String[] data;
|
||||
protected Session session;
|
||||
protected MessageConsumer consumer;
|
||||
protected MessageProducer producer;
|
||||
protected Destination consumerDestination;
|
||||
protected Destination producerDestination;
|
||||
protected List<Message> messages = createConcurrentList();
|
||||
protected boolean topic = true;
|
||||
protected boolean durable;
|
||||
protected int deliveryMode = DeliveryMode.PERSISTENT;
|
||||
protected final Object lock = new Object();
|
||||
protected boolean verbose;
|
||||
|
||||
/*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
String temp = System.getProperty("messageCount");
|
||||
|
||||
if (temp != null) {
|
||||
int i = Integer.parseInt(temp);
|
||||
if (i > 0) {
|
||||
messageCount = i;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.info("Message count for test case is: " + messageCount);
|
||||
data = new String[messageCount];
|
||||
|
||||
for (int i = 0; i < messageCount; i++) {
|
||||
data[i] = "Text for message: " + i + " at " + new Date();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends and consumes the messages.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSendReceive() throws Exception {
|
||||
messages.clear();
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
Message message = session.createTextMessage(data[i]);
|
||||
message.setStringProperty("stringProperty", data[i]);
|
||||
message.setIntProperty("intProperty", i);
|
||||
|
||||
if (verbose) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("About to send a message: " + message + " with text: " + data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
sendToProducer(producer, producerDestination, message);
|
||||
messageSent();
|
||||
}
|
||||
|
||||
assertMessagesAreReceived();
|
||||
LOG.info("" + data.length + " messages(s) received, closing down connections");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to a destination using the supplied producer
|
||||
* @param producer
|
||||
* @param producerDestination
|
||||
* @param message
|
||||
* @throws JMSException
|
||||
*/
|
||||
protected void sendToProducer(MessageProducer producer,
|
||||
Destination producerDestination, Message message) throws JMSException {
|
||||
producer.send(producerDestination, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts messages are received.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
protected void assertMessagesAreReceived() throws JMSException {
|
||||
waitForMessagesToBeDelivered();
|
||||
assertMessagesReceivedAreValid(messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the messages received are valid.
|
||||
*
|
||||
* @param receivedMessages - list of received messages.
|
||||
* @throws JMSException
|
||||
*/
|
||||
protected void assertMessagesReceivedAreValid(List<Message> receivedMessages) throws JMSException {
|
||||
List<Object> copyOfMessages = Arrays.asList(receivedMessages.toArray());
|
||||
int counter = 0;
|
||||
|
||||
if (data.length != copyOfMessages.size()) {
|
||||
for (Iterator<Object> iter = copyOfMessages.iterator(); iter.hasNext();) {
|
||||
TextMessage message = (TextMessage)iter.next();
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info("<== " + counter++ + " = " + message.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals("Not enough messages received", data.length, receivedMessages.size());
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
TextMessage received = (TextMessage)receivedMessages.get(i);
|
||||
String text = received.getText();
|
||||
String stringProperty = received.getStringProperty("stringProperty");
|
||||
int intProperty = received.getIntProperty("intProperty");
|
||||
|
||||
if (verbose) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.info("Received Text: " + text);
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals("Message: " + i, data[i], text);
|
||||
assertEquals(data[i], stringProperty);
|
||||
assertEquals(i, intProperty);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for messages to be delivered.
|
||||
*/
|
||||
protected void waitForMessagesToBeDelivered() {
|
||||
long maxWaitTime = 60000;
|
||||
long waitTime = maxWaitTime;
|
||||
long start = (maxWaitTime <= 0) ? 0 : System.currentTimeMillis();
|
||||
|
||||
synchronized (lock) {
|
||||
while (messages.size() < data.length && waitTime >= 0) {
|
||||
try {
|
||||
lock.wait(200);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
waitTime = maxWaitTime - (System.currentTimeMillis() - start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.jms.MessageListener#onMessage(javax.jms.Message)
|
||||
*/
|
||||
public synchronized void onMessage(Message message) {
|
||||
consumeMessage(message, messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumes messages.
|
||||
*
|
||||
* @param message - message to be consumed.
|
||||
* @param messageList -list of consumed messages.
|
||||
*/
|
||||
protected void consumeMessage(Message message, List<Message> messageList) {
|
||||
if (verbose) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.info("Received message: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
messageList.add(message);
|
||||
|
||||
if (messageList.size() >= data.length) {
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ArrayList as a synchronized list.
|
||||
*
|
||||
* @return List
|
||||
*/
|
||||
protected List<Message> createConcurrentList() {
|
||||
return Collections.synchronizedList(new ArrayList<Message>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Just a hook so can insert failure tests
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void messageSent() throws Exception {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,310 @@
|
|||
/**
|
||||
* 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.Date;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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.Session;
|
||||
import javax.jms.Topic;
|
||||
|
||||
import org.apache.activemq.broker.BrokerRegistry;
|
||||
import org.apache.activemq.broker.region.DestinationStatistics;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.util.Wait;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsSendReceiveWithMessageExpirationTest extends TestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JmsSendReceiveWithMessageExpirationTest.class);
|
||||
|
||||
protected int messageCount = 100;
|
||||
protected String[] data;
|
||||
protected Session session;
|
||||
protected Destination consumerDestination;
|
||||
protected Destination producerDestination;
|
||||
protected boolean durable;
|
||||
protected int deliveryMode = DeliveryMode.PERSISTENT;
|
||||
protected long timeToLive = 5000;
|
||||
protected boolean verbose;
|
||||
|
||||
protected Connection connection;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
|
||||
super.setUp();
|
||||
|
||||
data = new String[messageCount];
|
||||
|
||||
for (int i = 0; i < messageCount; i++) {
|
||||
data[i] = "Text for message: " + i + " at " + new Date();
|
||||
}
|
||||
|
||||
connectionFactory = createConnectionFactory();
|
||||
connection = createConnection();
|
||||
|
||||
if (durable) {
|
||||
connection.setClientID(getClass().getName());
|
||||
}
|
||||
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test consuming an expired queue.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testConsumeExpiredQueue() throws Exception {
|
||||
|
||||
MessageProducer producer = createProducer(timeToLive);
|
||||
|
||||
consumerDestination = session.createQueue(getConsumerSubject());
|
||||
producerDestination = session.createQueue(getProducerSubject());
|
||||
|
||||
MessageConsumer consumer = createConsumer();
|
||||
connection.start();
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
Message message = session.createTextMessage(data[i]);
|
||||
message.setStringProperty("stringProperty", data[i]);
|
||||
message.setIntProperty("intProperty", i);
|
||||
|
||||
if (verbose) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("About to send a queue message: " + message + " with text: " + data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
producer.send(producerDestination, message);
|
||||
}
|
||||
|
||||
// sleeps a second longer than the expiration time.
|
||||
// Basically waits till queue expires.
|
||||
Thread.sleep(timeToLive + 1000);
|
||||
|
||||
// message should have expired.
|
||||
assertNull(consumer.receive(1000));
|
||||
}
|
||||
|
||||
public void testConsumeExpiredQueueAndDlq() throws Exception {
|
||||
|
||||
MessageProducer producerNormal = createProducer(0);
|
||||
MessageProducer producerExpire = createProducer(500);
|
||||
|
||||
consumerDestination = session.createQueue("ActiveMQ.DLQ");
|
||||
MessageConsumer dlqConsumer = createConsumer();
|
||||
|
||||
consumerDestination = session.createQueue(getConsumerSubject());
|
||||
producerDestination = session.createQueue(getProducerSubject());
|
||||
|
||||
|
||||
Connection consumerConnection = createConnection();
|
||||
ActiveMQPrefetchPolicy prefetchPolicy = new ActiveMQPrefetchPolicy();
|
||||
prefetchPolicy.setAll(10);
|
||||
((ActiveMQConnection)consumerConnection).setPrefetchPolicy(prefetchPolicy);
|
||||
Session consumerSession = consumerConnection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
MessageConsumer consumer = consumerSession.createConsumer(consumerDestination);
|
||||
consumerConnection.start();
|
||||
connection.start();
|
||||
|
||||
String msgBody = new String(new byte[20*1024]);
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
Message message = session.createTextMessage(msgBody);
|
||||
producerExpire.send(producerDestination, message);
|
||||
}
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
Message message = session.createTextMessage(msgBody);
|
||||
producerNormal.send(producerDestination, message);
|
||||
}
|
||||
|
||||
Vector<Message> messages = new Vector<Message>();
|
||||
Message received;
|
||||
while ((received = consumer.receive(1000)) != null) {
|
||||
messages.add(received);
|
||||
if (messages.size() == 1) {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
}
|
||||
received.acknowledge();
|
||||
};
|
||||
|
||||
assertEquals("got all (normal plus one with ttl) messages", messageCount + 1, messages.size());
|
||||
|
||||
Vector<Message> dlqMessages = new Vector<Message>();
|
||||
while ((received = dlqConsumer.receive(1000)) != null) {
|
||||
dlqMessages.add(received);
|
||||
};
|
||||
|
||||
assertEquals("got dlq messages", data.length - 1, dlqMessages.size());
|
||||
|
||||
final DestinationStatistics view = getDestinationStatistics(BrokerRegistry.getInstance().findFirst(), ActiveMQDestination.transform(consumerDestination));
|
||||
|
||||
// wait for all to inflight to expire
|
||||
assertTrue("all inflight messages expired ", Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return view.getInflight().getCount() == 0;
|
||||
}
|
||||
}));
|
||||
assertEquals("Wrong inFlightCount: ", 0, view.getInflight().getCount());
|
||||
|
||||
LOG.info("Stats: received: " + messages.size() + ", messages: " + view.getMessages().getCount() + ", enqueues: " + view.getEnqueues().getCount() + ", dequeues: " + view.getDequeues().getCount()
|
||||
+ ", dispatched: " + view.getDispatched().getCount() + ", inflight: " + view.getInflight().getCount() + ", expired: " + view.getExpired().getCount());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends and consumes the messages to a queue destination.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testConsumeQueue() throws Exception {
|
||||
|
||||
MessageProducer producer = createProducer(0);
|
||||
|
||||
consumerDestination = session.createQueue(getConsumerSubject());
|
||||
producerDestination = session.createQueue(getProducerSubject());
|
||||
|
||||
MessageConsumer consumer = createConsumer();
|
||||
connection.start();
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
Message message = session.createTextMessage(data[i]);
|
||||
message.setStringProperty("stringProperty", data[i]);
|
||||
message.setIntProperty("intProperty", i);
|
||||
|
||||
if (verbose) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("About to send a queue message: " + message + " with text: " + data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
producer.send(producerDestination, message);
|
||||
}
|
||||
|
||||
// should receive a queue since there is no expiration.
|
||||
assertNotNull(consumer.receive(1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test consuming an expired topic.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testConsumeExpiredTopic() throws Exception {
|
||||
|
||||
MessageProducer producer = createProducer(timeToLive);
|
||||
|
||||
consumerDestination = session.createTopic(getConsumerSubject());
|
||||
producerDestination = session.createTopic(getProducerSubject());
|
||||
|
||||
MessageConsumer consumer = createConsumer();
|
||||
connection.start();
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
Message message = session.createTextMessage(data[i]);
|
||||
message.setStringProperty("stringProperty", data[i]);
|
||||
message.setIntProperty("intProperty", i);
|
||||
|
||||
if (verbose) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("About to send a topic message: " + message + " with text: " + data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
producer.send(producerDestination, message);
|
||||
}
|
||||
|
||||
// sleeps a second longer than the expiration time.
|
||||
// Basically waits till topic expires.
|
||||
Thread.sleep(timeToLive + 1000);
|
||||
|
||||
// message should have expired.
|
||||
assertNull(consumer.receive(1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends and consumes the messages to a topic destination.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testConsumeTopic() throws Exception {
|
||||
|
||||
MessageProducer producer = createProducer(0);
|
||||
|
||||
consumerDestination = session.createTopic(getConsumerSubject());
|
||||
producerDestination = session.createTopic(getProducerSubject());
|
||||
|
||||
MessageConsumer consumer = createConsumer();
|
||||
connection.start();
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
Message message = session.createTextMessage(data[i]);
|
||||
message.setStringProperty("stringProperty", data[i]);
|
||||
message.setIntProperty("intProperty", i);
|
||||
|
||||
if (verbose) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("About to send a topic message: " + message + " with text: " + data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
producer.send(producerDestination, message);
|
||||
}
|
||||
|
||||
// should receive a topic since there is no expiration.
|
||||
assertNotNull(consumer.receive(1000));
|
||||
}
|
||||
|
||||
protected MessageProducer createProducer(long timeToLive) throws JMSException {
|
||||
MessageProducer producer = session.createProducer(null);
|
||||
producer.setDeliveryMode(deliveryMode);
|
||||
producer.setTimeToLive(timeToLive);
|
||||
|
||||
return producer;
|
||||
}
|
||||
|
||||
protected MessageConsumer createConsumer() throws JMSException {
|
||||
if (durable) {
|
||||
LOG.info("Creating durable consumer");
|
||||
return session.createDurableSubscriber((Topic)consumerDestination, getName());
|
||||
}
|
||||
return session.createConsumer(consumerDestination);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
LOG.info("Dumping stats...");
|
||||
LOG.info("Closing down connection");
|
||||
|
||||
session.close();
|
||||
connection.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
/**
|
||||
* 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.concurrent.CountDownLatch;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsSendWithAsyncCallbackTest extends TestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JmsSendWithAsyncCallbackTest.class);
|
||||
|
||||
private Connection connection;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
connection = createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testAsyncCallbackIsFaster() throws JMSException, InterruptedException {
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue(getName());
|
||||
|
||||
// setup a consumer to drain messages..
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
}
|
||||
});
|
||||
|
||||
// warmup...
|
||||
for (int i = 0; i < 10; i++) {
|
||||
benchmarkNonCallbackRate();
|
||||
benchmarkCallbackRate();
|
||||
}
|
||||
|
||||
double callbackRate = benchmarkCallbackRate();
|
||||
double nonCallbackRate = benchmarkNonCallbackRate();
|
||||
|
||||
LOG.info(String.format("AsyncCallback Send rate: %,.2f m/s", callbackRate));
|
||||
LOG.info(String.format("NonAsyncCallback Send rate: %,.2f m/s", nonCallbackRate));
|
||||
|
||||
// The async style HAS to be faster than the non-async style..
|
||||
assertTrue("async rate[" + callbackRate + "] should beat non-async rate[" + nonCallbackRate + "]", callbackRate / nonCallbackRate > 1.5);
|
||||
}
|
||||
|
||||
private double benchmarkNonCallbackRate() throws JMSException {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue(getName());
|
||||
int count = 1000;
|
||||
ActiveMQMessageProducer producer = (ActiveMQMessageProducer) session.createProducer(queue);
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
long start = System.currentTimeMillis();
|
||||
for (int i = 0; i < count; i++) {
|
||||
producer.send(session.createTextMessage("Hello"));
|
||||
}
|
||||
return 1000.0 * count / (System.currentTimeMillis() - start);
|
||||
}
|
||||
|
||||
private double benchmarkCallbackRate() throws JMSException, InterruptedException {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue queue = session.createQueue(getName());
|
||||
int count = 1000;
|
||||
final CountDownLatch messagesSent = new CountDownLatch(count);
|
||||
ActiveMQMessageProducer producer = (ActiveMQMessageProducer) session.createProducer(queue);
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
long start = System.currentTimeMillis();
|
||||
for (int i = 0; i < count; i++) {
|
||||
producer.send(session.createTextMessage("Hello"), new AsyncCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
messagesSent.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(JMSException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
messagesSent.await();
|
||||
return 1000.0 * count / (System.currentTimeMillis() - start);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,294 @@
|
|||
/**
|
||||
* 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.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
|
||||
/**
|
||||
* Testcases to see if Session.recover() work.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JmsSessionRecoverTest extends TestCase {
|
||||
|
||||
private Connection connection;
|
||||
private ActiveMQConnectionFactory factory;
|
||||
private Destination dest;
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
factory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
connection = factory.createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws JMSException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void testQueueSynchRecover() throws JMSException, InterruptedException {
|
||||
dest = new ActiveMQQueue("Queue-" + System.currentTimeMillis());
|
||||
doTestSynchRecover();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws JMSException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void testQueueAsynchRecover() throws JMSException, InterruptedException {
|
||||
dest = new ActiveMQQueue("Queue-" + System.currentTimeMillis());
|
||||
doTestAsynchRecover();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws JMSException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void testTopicSynchRecover() throws JMSException, InterruptedException {
|
||||
dest = new ActiveMQTopic("Topic-" + System.currentTimeMillis());
|
||||
doTestSynchRecover();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws JMSException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void testTopicAsynchRecover() throws JMSException, InterruptedException {
|
||||
dest = new ActiveMQTopic("Topic-" + System.currentTimeMillis());
|
||||
doTestAsynchRecover();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws JMSException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void testQueueAsynchRecoverWithAutoAck() throws JMSException, InterruptedException {
|
||||
dest = new ActiveMQQueue("Queue-" + System.currentTimeMillis());
|
||||
doTestAsynchRecoverWithAutoAck();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws JMSException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void testTopicAsynchRecoverWithAutoAck() throws JMSException, InterruptedException {
|
||||
dest = new ActiveMQTopic("Topic-" + System.currentTimeMillis());
|
||||
doTestAsynchRecoverWithAutoAck();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to make sure that a Sync recover works.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void doTestSynchRecover() throws JMSException {
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
MessageConsumer consumer = session.createConsumer(dest);
|
||||
connection.start();
|
||||
|
||||
MessageProducer producer = session.createProducer(dest);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
producer.send(session.createTextMessage("First"));
|
||||
producer.send(session.createTextMessage("Second"));
|
||||
|
||||
TextMessage message = (TextMessage)consumer.receive(1000);
|
||||
assertEquals("First", message.getText());
|
||||
assertFalse(message.getJMSRedelivered());
|
||||
message.acknowledge();
|
||||
|
||||
message = (TextMessage)consumer.receive(1000);
|
||||
assertEquals("Second", message.getText());
|
||||
assertFalse(message.getJMSRedelivered());
|
||||
|
||||
session.recover();
|
||||
|
||||
message = (TextMessage)consumer.receive(2000);
|
||||
assertEquals("Second", message.getText());
|
||||
assertTrue(message.getJMSRedelivered());
|
||||
|
||||
message.acknowledge();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to make sure that a Async recover works.
|
||||
*
|
||||
* @throws JMSException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void doTestAsynchRecover() throws JMSException, InterruptedException {
|
||||
|
||||
final Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
final String errorMessage[] = new String[] {null};
|
||||
final CountDownLatch doneCountDownLatch = new CountDownLatch(1);
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(dest);
|
||||
|
||||
MessageProducer producer = session.createProducer(dest);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
producer.send(session.createTextMessage("First"));
|
||||
producer.send(session.createTextMessage("Second"));
|
||||
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
int counter;
|
||||
|
||||
public void onMessage(Message msg) {
|
||||
counter++;
|
||||
try {
|
||||
TextMessage message = (TextMessage)msg;
|
||||
switch (counter) {
|
||||
case 1:
|
||||
assertEquals("First", message.getText());
|
||||
assertFalse(message.getJMSRedelivered());
|
||||
message.acknowledge();
|
||||
|
||||
break;
|
||||
case 2:
|
||||
assertEquals("Second", message.getText());
|
||||
assertFalse(message.getJMSRedelivered());
|
||||
session.recover();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
assertEquals("Second", message.getText());
|
||||
assertTrue(message.getJMSRedelivered());
|
||||
message.acknowledge();
|
||||
doneCountDownLatch.countDown();
|
||||
break;
|
||||
|
||||
default:
|
||||
errorMessage[0] = "Got too many messages: " + counter;
|
||||
doneCountDownLatch.countDown();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
errorMessage[0] = "Got exception: " + e;
|
||||
doneCountDownLatch.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
connection.start();
|
||||
|
||||
if (doneCountDownLatch.await(5, TimeUnit.SECONDS)) {
|
||||
if (errorMessage[0] != null) {
|
||||
fail(errorMessage[0]);
|
||||
}
|
||||
} else {
|
||||
fail("Timeout waiting for async message delivery to complete.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to make sure that a Async recover works when using AUTO_ACKNOWLEDGE.
|
||||
*
|
||||
* @throws JMSException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void doTestAsynchRecoverWithAutoAck() throws JMSException, InterruptedException {
|
||||
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final String errorMessage[] = new String[] {null};
|
||||
final CountDownLatch doneCountDownLatch = new CountDownLatch(1);
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(dest);
|
||||
|
||||
MessageProducer producer = session.createProducer(dest);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
producer.send(session.createTextMessage("First"));
|
||||
producer.send(session.createTextMessage("Second"));
|
||||
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
int counter;
|
||||
|
||||
public void onMessage(Message msg) {
|
||||
counter++;
|
||||
try {
|
||||
TextMessage message = (TextMessage)msg;
|
||||
switch (counter) {
|
||||
case 1:
|
||||
assertEquals("First", message.getText());
|
||||
assertFalse(message.getJMSRedelivered());
|
||||
break;
|
||||
case 2:
|
||||
// This should rollback the delivery of this message..
|
||||
// and re-deliver.
|
||||
assertEquals("Second", message.getText());
|
||||
assertFalse(message.getJMSRedelivered());
|
||||
session.recover();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
assertEquals("Second", message.getText());
|
||||
assertTrue(message.getJMSRedelivered());
|
||||
doneCountDownLatch.countDown();
|
||||
break;
|
||||
|
||||
default:
|
||||
errorMessage[0] = "Got too many messages: " + counter;
|
||||
doneCountDownLatch.countDown();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
errorMessage[0] = "Got exception: " + e;
|
||||
doneCountDownLatch.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
connection.start();
|
||||
|
||||
if (doneCountDownLatch.await(5000, TimeUnit.SECONDS)) {
|
||||
if (errorMessage[0] != null) {
|
||||
fail(errorMessage[0]);
|
||||
}
|
||||
} else {
|
||||
fail("Timeout waiting for async message delivery to complete.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,377 @@
|
|||
/**
|
||||
* 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.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.InvalidDestinationException;
|
||||
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.TemporaryQueue;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.transport.TransportListener;
|
||||
import org.apache.activemq.transport.vm.VMTransport;
|
||||
import org.apache.activemq.util.Wait;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @version
|
||||
*/
|
||||
public class JmsTempDestinationTest extends TestCase {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JmsTempDestinationTest.class);
|
||||
private Connection connection;
|
||||
private ActiveMQConnectionFactory factory;
|
||||
protected List<Connection> connections = Collections.synchronizedList(new ArrayList<Connection>());
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
factory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
factory.setAlwaysSyncSend(true);
|
||||
connection = factory.createConnection();
|
||||
connections.add(connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
for (Iterator<Connection> iter = connections.iterator(); iter.hasNext();) {
|
||||
Connection conn = iter.next();
|
||||
try {
|
||||
conn.close();
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure Temp destination can only be consumed by local connection
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testTempDestOnlyConsumedByLocalConn() throws JMSException {
|
||||
connection.start();
|
||||
|
||||
Session tempSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
TemporaryQueue queue = tempSession.createTemporaryQueue();
|
||||
MessageProducer producer = tempSession.createProducer(queue);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
TextMessage message = tempSession.createTextMessage("First");
|
||||
producer.send(message);
|
||||
|
||||
// temp destination should not be consume when using another connection
|
||||
Connection otherConnection = factory.createConnection();
|
||||
connections.add(otherConnection);
|
||||
Session otherSession = otherConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
TemporaryQueue otherQueue = otherSession.createTemporaryQueue();
|
||||
MessageConsumer consumer = otherSession.createConsumer(otherQueue);
|
||||
Message msg = consumer.receive(3000);
|
||||
assertNull(msg);
|
||||
|
||||
// should throw InvalidDestinationException when consuming a temp
|
||||
// destination from another connection
|
||||
try {
|
||||
consumer = otherSession.createConsumer(queue);
|
||||
fail("Send should fail since temp destination should be used from another connection");
|
||||
} catch (InvalidDestinationException e) {
|
||||
assertTrue("failed to throw an exception", true);
|
||||
}
|
||||
|
||||
// should be able to consume temp destination from the same connection
|
||||
consumer = tempSession.createConsumer(queue);
|
||||
msg = consumer.receive(3000);
|
||||
assertNotNull(msg);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that a temp queue does not drop message if there is an active
|
||||
* consumers.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testTempQueueHoldsMessagesWithConsumers() throws JMSException {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue queue = session.createTemporaryQueue();
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
connection.start();
|
||||
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
TextMessage message = session.createTextMessage("Hello");
|
||||
producer.send(message);
|
||||
|
||||
Message message2 = consumer.receive(1000);
|
||||
assertNotNull(message2);
|
||||
assertTrue("Expected message to be a TextMessage", message2 instanceof TextMessage);
|
||||
assertTrue("Expected message to be a '" + message.getText() + "'", ((TextMessage)message2).getText().equals(message.getText()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that a temp queue does not drop message if there are no active
|
||||
* consumers.
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testTempQueueHoldsMessagesWithoutConsumers() throws JMSException {
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue queue = session.createTemporaryQueue();
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
TextMessage message = session.createTextMessage("Hello");
|
||||
producer.send(message);
|
||||
|
||||
connection.start();
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
Message message2 = consumer.receive(3000);
|
||||
assertNotNull(message2);
|
||||
assertTrue("Expected message to be a TextMessage", message2 instanceof TextMessage);
|
||||
assertTrue("Expected message to be a '" + message.getText() + "'", ((TextMessage)message2).getText().equals(message.getText()));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test temp queue works under load
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testTmpQueueWorksUnderLoad() throws JMSException {
|
||||
int count = 500;
|
||||
int dataSize = 1024;
|
||||
|
||||
ArrayList<BytesMessage> list = new ArrayList<BytesMessage>(count);
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue queue = session.createTemporaryQueue();
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
|
||||
byte[] data = new byte[dataSize];
|
||||
for (int i = 0; i < count; i++) {
|
||||
BytesMessage message = session.createBytesMessage();
|
||||
message.writeBytes(data);
|
||||
message.setIntProperty("c", i);
|
||||
producer.send(message);
|
||||
list.add(message);
|
||||
}
|
||||
|
||||
connection.start();
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
for (int i = 0; i < count; i++) {
|
||||
Message message2 = consumer.receive(2000);
|
||||
assertTrue(message2 != null);
|
||||
assertEquals(i, message2.getIntProperty("c"));
|
||||
assertTrue(message2.equals(list.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure you cannot publish to a temp destination that does not exist
|
||||
* anymore.
|
||||
*
|
||||
* @throws JMSException
|
||||
* @throws InterruptedException
|
||||
* @throws URISyntaxException
|
||||
*/
|
||||
public void testPublishFailsForClosedConnection() throws Exception {
|
||||
|
||||
Connection tempConnection = factory.createConnection();
|
||||
connections.add(tempConnection);
|
||||
Session tempSession = tempConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final TemporaryQueue queue = tempSession.createTemporaryQueue();
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
connection.start();
|
||||
|
||||
final ActiveMQConnection activeMQConnection = (ActiveMQConnection) connection;
|
||||
assertTrue("creation advisory received in time with async dispatch", Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return activeMQConnection.activeTempDestinations.containsKey(queue);
|
||||
}
|
||||
}));
|
||||
|
||||
// This message delivery should work since the temp connection is still
|
||||
// open.
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
TextMessage message = session.createTextMessage("First");
|
||||
producer.send(message);
|
||||
|
||||
// Closing the connection should destroy the temp queue that was
|
||||
// created.
|
||||
tempConnection.close();
|
||||
Thread.sleep(5000); // Wait a little bit to let the delete take effect.
|
||||
|
||||
// This message delivery NOT should work since the temp connection is
|
||||
// now closed.
|
||||
try {
|
||||
message = session.createTextMessage("Hello");
|
||||
producer.send(message);
|
||||
fail("Send should fail since temp destination should not exist anymore.");
|
||||
} catch (JMSException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure you cannot publish to a temp destination that does not exist
|
||||
* anymore.
|
||||
*
|
||||
* @throws JMSException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void testPublishFailsForDestroyedTempDestination() throws Exception {
|
||||
|
||||
Connection tempConnection = factory.createConnection();
|
||||
connections.add(tempConnection);
|
||||
Session tempSession = tempConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final TemporaryQueue queue = tempSession.createTemporaryQueue();
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
connection.start();
|
||||
|
||||
final ActiveMQConnection activeMQConnection = (ActiveMQConnection) connection;
|
||||
assertTrue("creation advisory received in time with async dispatch", Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return activeMQConnection.activeTempDestinations.containsKey(queue);
|
||||
}
|
||||
}));
|
||||
|
||||
// This message delivery should work since the temp connection is still
|
||||
// open.
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
TextMessage message = session.createTextMessage("First");
|
||||
producer.send(message);
|
||||
|
||||
// deleting the Queue will cause sends to fail
|
||||
queue.delete();
|
||||
Thread.sleep(5000); // Wait a little bit to let the delete take effect.
|
||||
|
||||
// This message delivery NOT should work since the temp connection is
|
||||
// now closed.
|
||||
try {
|
||||
message = session.createTextMessage("Hello");
|
||||
producer.send(message);
|
||||
fail("Send should fail since temp destination should not exist anymore.");
|
||||
} catch (JMSException e) {
|
||||
assertTrue("failed to throw an exception", true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test you can't delete a Destination with Active Subscribers
|
||||
*
|
||||
* @throws JMSException
|
||||
*/
|
||||
public void testDeleteDestinationWithSubscribersFails() throws JMSException {
|
||||
Connection connection = factory.createConnection();
|
||||
connections.add(connection);
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
TemporaryQueue queue = session.createTemporaryQueue();
|
||||
|
||||
connection.start();
|
||||
|
||||
session.createConsumer(queue);
|
||||
|
||||
// This message delivery should NOT work since the temp connection is
|
||||
// now closed.
|
||||
try {
|
||||
queue.delete();
|
||||
fail("Should fail as Subscribers are active");
|
||||
} catch (JMSException e) {
|
||||
assertTrue("failed to throw an exception", true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSlowConsumerDoesNotBlockFastTempUsers() throws Exception {
|
||||
ActiveMQConnectionFactory advisoryConnFactory = new ActiveMQConnectionFactory("vm://localhost?asyncQueueDepth=20");
|
||||
Connection connection = advisoryConnFactory.createConnection();
|
||||
connections.add(connection);
|
||||
connection.start();
|
||||
|
||||
final CountDownLatch done = new CountDownLatch(1);
|
||||
final AtomicBoolean ok = new AtomicBoolean(true);
|
||||
final AtomicBoolean first = new AtomicBoolean(true);
|
||||
VMTransport t = ((ActiveMQConnection)connection).getTransport().narrow(VMTransport.class);
|
||||
t.setTransportListener(new TransportListener() {
|
||||
@Override
|
||||
public void onCommand(Object command) {
|
||||
// block first dispatch for a while so broker backs up, but other connection should be able to proceed
|
||||
if (first.compareAndSet(true, false)) {
|
||||
try {
|
||||
ok.set(done.await(35, TimeUnit.SECONDS));
|
||||
LOG.info("Done waiting: " + ok.get());
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(IOException error) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transportInterupted() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transportResumed() {
|
||||
}
|
||||
});
|
||||
|
||||
connection = factory.createConnection();
|
||||
connections.add(connection);
|
||||
((ActiveMQConnection)connection).setWatchTopicAdvisories(false);
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
for (int i=0; i<2500; i++) {
|
||||
TemporaryQueue queue = session.createTemporaryQueue();
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
consumer.close();
|
||||
queue.delete();
|
||||
}
|
||||
LOG.info("Done with work: " + ok.get());
|
||||
done.countDown();
|
||||
assertTrue("ok", ok.get());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/**
|
||||
* 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.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.jms.Connection;
|
||||
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 org.apache.activemq.broker.BrokerFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
|
||||
/**
|
||||
* Test cases used to test the JMS message consumer.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JmsTestSupport extends CombinationTestSupport {
|
||||
|
||||
static final private AtomicLong TEST_COUNTER = new AtomicLong();
|
||||
public String userName;
|
||||
public String password;
|
||||
public String messageTextPrefix = "";
|
||||
|
||||
protected ConnectionFactory factory;
|
||||
protected ActiveMQConnection connection;
|
||||
protected BrokerService broker;
|
||||
|
||||
protected List<Connection> connections = Collections.synchronizedList(new ArrayList<Connection>());
|
||||
|
||||
// /////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Test support methods.
|
||||
//
|
||||
// /////////////////////////////////////////////////////////////////
|
||||
protected ActiveMQDestination createDestination(Session session, byte type) throws JMSException {
|
||||
String testMethod = getName();
|
||||
if( testMethod.indexOf(" ")>0 ) {
|
||||
testMethod = testMethod.substring(0, testMethod.indexOf(" "));
|
||||
}
|
||||
String name = "TEST." + getClass().getName() + "." +testMethod+"."+TEST_COUNTER.getAndIncrement();
|
||||
switch (type) {
|
||||
case ActiveMQDestination.QUEUE_TYPE:
|
||||
return (ActiveMQDestination)session.createQueue(name);
|
||||
case ActiveMQDestination.TOPIC_TYPE:
|
||||
return (ActiveMQDestination)session.createTopic(name);
|
||||
case ActiveMQDestination.TEMP_QUEUE_TYPE:
|
||||
return (ActiveMQDestination)session.createTemporaryQueue();
|
||||
case ActiveMQDestination.TEMP_TOPIC_TYPE:
|
||||
return (ActiveMQDestination)session.createTemporaryTopic();
|
||||
default:
|
||||
throw new IllegalArgumentException("type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendMessages(Destination destination, int count) throws Exception {
|
||||
ConnectionFactory factory = createConnectionFactory();
|
||||
Connection connection = factory.createConnection();
|
||||
connection.start();
|
||||
sendMessages(connection, destination, count);
|
||||
connection.close();
|
||||
}
|
||||
|
||||
protected void sendMessages(Connection connection, Destination destination, int count) throws JMSException {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
sendMessages(session, destination, count);
|
||||
session.close();
|
||||
}
|
||||
|
||||
protected void sendMessages(Session session, Destination destination, int count) throws JMSException {
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
sendMessages(session, producer, count);
|
||||
producer.close();
|
||||
}
|
||||
|
||||
protected void sendMessages(Session session, MessageProducer producer, int count) throws JMSException {
|
||||
for (int i = 0; i < count; i++) {
|
||||
producer.send(session.createTextMessage(messageTextPrefix + i));
|
||||
}
|
||||
}
|
||||
|
||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory("vm://localhost");
|
||||
}
|
||||
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
return BrokerFactory.createBroker(new URI("broker://()/localhost?persistent=false"));
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
if (System.getProperty("basedir") == null) {
|
||||
File file = new File(".");
|
||||
System.setProperty("basedir", file.getAbsolutePath());
|
||||
}
|
||||
|
||||
broker = createBroker();
|
||||
broker.start();
|
||||
factory = createConnectionFactory();
|
||||
connection = (ActiveMQConnection)factory.createConnection(userName, password);
|
||||
connections.add(connection);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
for (Iterator<Connection> iter = connections.iterator(); iter.hasNext();) {
|
||||
Connection conn = iter.next();
|
||||
try {
|
||||
conn.close();
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
iter.remove();
|
||||
}
|
||||
broker.stop();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
protected void safeClose(Connection c) {
|
||||
try {
|
||||
c.close();
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
|
||||
protected void safeClose(Session s) {
|
||||
try {
|
||||
s.close();
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
|
||||
protected void safeClose(MessageConsumer c) {
|
||||
try {
|
||||
c.close();
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
|
||||
protected void safeClose(MessageProducer p) {
|
||||
try {
|
||||
p.close();
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
|
||||
protected void profilerPause(String prompt) throws IOException {
|
||||
if (System.getProperty("profiler") != null) {
|
||||
pause(prompt);
|
||||
}
|
||||
}
|
||||
|
||||
protected void pause(String prompt) throws IOException {
|
||||
System.out.println();
|
||||
System.out.println(prompt + "> Press enter to continue: ");
|
||||
while (System.in.read() != '\n') {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* 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.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.Topic;
|
||||
|
||||
import org.apache.activemq.test.JmsTopicSendReceiveTest;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsTopicCompositeSendReceiveTest extends JmsTopicSendReceiveTest {
|
||||
private static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory
|
||||
.getLog(JmsTopicCompositeSendReceiveTest.class);
|
||||
|
||||
Destination consumerDestination2;
|
||||
MessageConsumer consumer2;
|
||||
|
||||
/**
|
||||
* Sets a test to have a queue destination and non-persistent delivery mode.
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
protected void setUp() throws Exception {
|
||||
deliveryMode = DeliveryMode.NON_PERSISTENT;
|
||||
super.setUp();
|
||||
consumerDestination2 = consumeSession.createTopic("FOO.BAR.HUMBUG2");
|
||||
LOG.info("Created consumer destination: " + consumerDestination2 + " of type: " + consumerDestination2.getClass());
|
||||
if (durable) {
|
||||
LOG.info("Creating durable consumer");
|
||||
consumer2 = consumeSession.createDurableSubscriber((Topic) consumerDestination2, getName());
|
||||
} else {
|
||||
consumer2 = consumeSession.createConsumer(consumerDestination2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the consumer subject.
|
||||
*
|
||||
* @return String - consumer subject
|
||||
* @see org.apache.activemq.test.TestSupport#getConsumerSubject()
|
||||
*/
|
||||
protected String getConsumerSubject() {
|
||||
return "FOO.BAR.HUMBUG";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the producer subject.
|
||||
*
|
||||
* @return String - producer subject
|
||||
* @see org.apache.activemq.test.TestSupport#getProducerSubject()
|
||||
*/
|
||||
protected String getProducerSubject() {
|
||||
return "FOO.BAR.HUMBUG,FOO.BAR.HUMBUG2";
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if all the messages sent are being received.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSendReceive() throws Exception {
|
||||
super.testSendReceive();
|
||||
messages.clear();
|
||||
consumer2.setMessageListener(this);
|
||||
assertMessagesAreReceived();
|
||||
LOG.info("" + data.length + " messages(s) received, closing down connections");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/**
|
||||
* 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.Destination;
|
||||
import javax.jms.JMSException;
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsTopicRedeliverTest extends TestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JmsTopicRedeliverTest.class);
|
||||
|
||||
protected Connection connection;
|
||||
protected Session session;
|
||||
protected Session consumeSession;
|
||||
protected MessageConsumer consumer;
|
||||
protected MessageProducer producer;
|
||||
protected Destination consumerDestination;
|
||||
protected Destination producerDestination;
|
||||
protected boolean topic = true;
|
||||
protected boolean durable;
|
||||
protected boolean verbose;
|
||||
protected long initRedeliveryDelay;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
connectionFactory = createConnectionFactory();
|
||||
connection = createConnection();
|
||||
initRedeliveryDelay = ((ActiveMQConnection)connection).getRedeliveryPolicy().getInitialRedeliveryDelay();
|
||||
|
||||
if (durable) {
|
||||
connection.setClientID(getClass().getName());
|
||||
}
|
||||
|
||||
LOG.info("Created connection: " + connection);
|
||||
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
consumeSession = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
|
||||
LOG.info("Created session: " + session);
|
||||
LOG.info("Created consumeSession: " + consumeSession);
|
||||
producer = session.createProducer(null);
|
||||
// producer.setDeliveryMode(deliveryMode);
|
||||
|
||||
LOG.info("Created producer: " + producer);
|
||||
|
||||
if (topic) {
|
||||
consumerDestination = session.createTopic(getConsumerSubject());
|
||||
producerDestination = session.createTopic(getProducerSubject());
|
||||
} else {
|
||||
consumerDestination = session.createQueue(getConsumerSubject());
|
||||
producerDestination = session.createQueue(getProducerSubject());
|
||||
}
|
||||
|
||||
LOG.info("Created consumer destination: " + consumerDestination + " of type: " + consumerDestination.getClass());
|
||||
LOG.info("Created producer destination: " + producerDestination + " of type: " + producerDestination.getClass());
|
||||
consumer = createConsumer();
|
||||
connection.start();
|
||||
|
||||
LOG.info("Created connection: " + connection);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the consumer subject.
|
||||
*
|
||||
* @return String - consumer subject
|
||||
* @see org.apache.activemq.test.TestSupport#getConsumerSubject()
|
||||
*/
|
||||
protected String getConsumerSubject() {
|
||||
return "TEST";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the producer subject.
|
||||
*
|
||||
* @return String - producer subject
|
||||
* @see org.apache.activemq.test.TestSupport#getProducerSubject()
|
||||
*/
|
||||
protected String getProducerSubject() {
|
||||
return "TEST";
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends and consumes the messages.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testRecover() throws Exception {
|
||||
String text = "TEST";
|
||||
Message sendMessage = session.createTextMessage(text);
|
||||
|
||||
if (verbose) {
|
||||
LOG.info("About to send a message: " + sendMessage + " with text: " + text);
|
||||
}
|
||||
producer.send(producerDestination, sendMessage);
|
||||
|
||||
// receive but don't acknowledge
|
||||
Message unackMessage = consumer.receive(initRedeliveryDelay + 1000);
|
||||
assertNotNull(unackMessage);
|
||||
String unackId = unackMessage.getJMSMessageID();
|
||||
assertEquals(((TextMessage)unackMessage).getText(), text);
|
||||
assertFalse(unackMessage.getJMSRedelivered());
|
||||
// assertEquals(unackMessage.getIntProperty("JMSXDeliveryCount"),1);
|
||||
|
||||
// receive then acknowledge
|
||||
consumeSession.recover();
|
||||
Message ackMessage = consumer.receive(initRedeliveryDelay + 1000);
|
||||
assertNotNull(ackMessage);
|
||||
ackMessage.acknowledge();
|
||||
String ackId = ackMessage.getJMSMessageID();
|
||||
assertEquals(((TextMessage)ackMessage).getText(), text);
|
||||
assertTrue(ackMessage.getJMSRedelivered());
|
||||
// assertEquals(ackMessage.getIntProperty("JMSXDeliveryCount"),2);
|
||||
assertEquals(unackId, ackId);
|
||||
consumeSession.recover();
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
protected MessageConsumer createConsumer() throws JMSException {
|
||||
if (durable) {
|
||||
LOG.info("Creating durable consumer");
|
||||
return consumeSession.createDurableSubscriber((Topic)consumerDestination, getName());
|
||||
}
|
||||
return consumeSession.createConsumer(consumerDestination);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
/**
|
||||
* 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.List;
|
||||
import java.util.Vector;
|
||||
|
||||
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 javax.jms.TemporaryTopic;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.test.TestSupport;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsTopicRequestReplyTest extends TestSupport implements MessageListener {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JmsTopicRequestReplyTest.class);
|
||||
|
||||
protected boolean useAsyncConsume;
|
||||
private Connection serverConnection;
|
||||
private Connection clientConnection;
|
||||
private MessageProducer replyProducer;
|
||||
private Session serverSession;
|
||||
private Destination requestDestination;
|
||||
private List<JMSException> failures = new Vector<JMSException>();
|
||||
private boolean dynamicallyCreateProducer;
|
||||
private String clientSideClientID;
|
||||
|
||||
public void testSendAndReceive() throws Exception {
|
||||
clientConnection = createConnection();
|
||||
clientConnection.setClientID("ClientConnection:" + getSubject());
|
||||
|
||||
Session session = clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
clientConnection.start();
|
||||
|
||||
Destination replyDestination = createTemporaryDestination(session);
|
||||
|
||||
// lets test the destination
|
||||
clientSideClientID = clientConnection.getClientID();
|
||||
|
||||
// TODO
|
||||
// String value = ActiveMQDestination.getClientId((ActiveMQDestination)
|
||||
// replyDestination);
|
||||
// assertEquals("clientID from the temporary destination must be the
|
||||
// same", clientSideClientID, value);
|
||||
LOG.info("Both the clientID and destination clientID match properly: " + clientSideClientID);
|
||||
|
||||
/* build queues */
|
||||
MessageProducer requestProducer = session.createProducer(requestDestination);
|
||||
MessageConsumer replyConsumer = session.createConsumer(replyDestination);
|
||||
|
||||
/* build requestmessage */
|
||||
TextMessage requestMessage = session.createTextMessage("Olivier");
|
||||
requestMessage.setJMSReplyTo(replyDestination);
|
||||
requestProducer.send(requestMessage);
|
||||
|
||||
LOG.info("Sent request.");
|
||||
LOG.info(requestMessage.toString());
|
||||
|
||||
Message msg = replyConsumer.receive(5000);
|
||||
|
||||
if (msg instanceof TextMessage) {
|
||||
TextMessage replyMessage = (TextMessage)msg;
|
||||
LOG.info("Received reply.");
|
||||
LOG.info(replyMessage.toString());
|
||||
assertEquals("Wrong message content", "Hello: Olivier", replyMessage.getText());
|
||||
} else {
|
||||
fail("Should have received a reply by now");
|
||||
}
|
||||
replyConsumer.close();
|
||||
deleteTemporaryDestination(replyDestination);
|
||||
|
||||
assertEquals("Should not have had any failures: " + failures, 0, failures.size());
|
||||
}
|
||||
|
||||
public void testSendAndReceiveWithDynamicallyCreatedProducer() throws Exception {
|
||||
dynamicallyCreateProducer = true;
|
||||
testSendAndReceive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the asynchronous subscription mechanism
|
||||
*/
|
||||
public void onMessage(Message message) {
|
||||
try {
|
||||
TextMessage requestMessage = (TextMessage)message;
|
||||
|
||||
LOG.info("Received request.");
|
||||
LOG.info(requestMessage.toString());
|
||||
|
||||
Destination replyDestination = requestMessage.getJMSReplyTo();
|
||||
|
||||
// TODO
|
||||
// String value =
|
||||
// ActiveMQDestination.getClientId((ActiveMQDestination)
|
||||
// replyDestination);
|
||||
// assertEquals("clientID from the temporary destination must be the
|
||||
// same", clientSideClientID, value);
|
||||
|
||||
TextMessage replyMessage = serverSession.createTextMessage("Hello: " + requestMessage.getText());
|
||||
|
||||
replyMessage.setJMSCorrelationID(requestMessage.getJMSMessageID());
|
||||
|
||||
if (dynamicallyCreateProducer) {
|
||||
replyProducer = serverSession.createProducer(replyDestination);
|
||||
replyProducer.send(replyMessage);
|
||||
} else {
|
||||
replyProducer.send(replyDestination, replyMessage);
|
||||
}
|
||||
|
||||
LOG.info("Sent reply.");
|
||||
LOG.info(replyMessage.toString());
|
||||
} catch (JMSException e) {
|
||||
onException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the synchronous subscription mechanism
|
||||
*/
|
||||
protected void syncConsumeLoop(MessageConsumer requestConsumer) {
|
||||
try {
|
||||
Message message = requestConsumer.receive(5000);
|
||||
if (message != null) {
|
||||
onMessage(message);
|
||||
} else {
|
||||
LOG.error("No message received");
|
||||
}
|
||||
} catch (JMSException e) {
|
||||
onException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
serverConnection = createConnection();
|
||||
serverConnection.setClientID("serverConnection:" + getSubject());
|
||||
serverSession = serverConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
replyProducer = serverSession.createProducer(null);
|
||||
|
||||
requestDestination = createDestination(serverSession);
|
||||
|
||||
/* build queues */
|
||||
final MessageConsumer requestConsumer = serverSession.createConsumer(requestDestination);
|
||||
if (useAsyncConsume) {
|
||||
requestConsumer.setMessageListener(this);
|
||||
} else {
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
syncConsumeLoop(requestConsumer);
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
}
|
||||
serverConnection.start();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
serverConnection.close();
|
||||
clientConnection.stop();
|
||||
clientConnection.close();
|
||||
}
|
||||
|
||||
protected void onException(JMSException e) {
|
||||
LOG.info("Caught: " + e);
|
||||
e.printStackTrace();
|
||||
failures.add(e);
|
||||
}
|
||||
|
||||
protected Destination createDestination(Session session) throws JMSException {
|
||||
if (topic) {
|
||||
return session.createTopic(getSubject());
|
||||
}
|
||||
return session.createQueue(getSubject());
|
||||
}
|
||||
|
||||
protected Destination createTemporaryDestination(Session session) throws JMSException {
|
||||
if (topic) {
|
||||
return session.createTemporaryTopic();
|
||||
}
|
||||
return session.createTemporaryQueue();
|
||||
}
|
||||
|
||||
protected void deleteTemporaryDestination(Destination dest) throws JMSException {
|
||||
if (topic) {
|
||||
((TemporaryTopic)dest).delete();
|
||||
} else {
|
||||
((TemporaryQueue)dest).delete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/**
|
||||
* 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.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSException;
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsTopicSelectorTest extends TestSupport {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JmsTopicSelectorTest.class);
|
||||
|
||||
protected Connection connection;
|
||||
protected Session session;
|
||||
protected MessageConsumer consumer;
|
||||
protected MessageProducer producer;
|
||||
protected Destination consumerDestination;
|
||||
protected Destination producerDestination;
|
||||
protected boolean topic = true;
|
||||
protected boolean durable;
|
||||
protected int deliveryMode = DeliveryMode.PERSISTENT;
|
||||
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
connectionFactory = createConnectionFactory();
|
||||
connection = createConnection();
|
||||
if (durable) {
|
||||
connection.setClientID(getClass().getName());
|
||||
}
|
||||
|
||||
LOG.info("Created connection: " + connection);
|
||||
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
LOG.info("Created session: " + session);
|
||||
|
||||
if (topic) {
|
||||
consumerDestination = session.createTopic(getConsumerSubject());
|
||||
producerDestination = session.createTopic(getProducerSubject());
|
||||
} else {
|
||||
consumerDestination = session.createQueue(getConsumerSubject());
|
||||
producerDestination = session.createQueue(getProducerSubject());
|
||||
}
|
||||
|
||||
LOG.info("Created consumer destination: " + consumerDestination + " of type: " + consumerDestination.getClass());
|
||||
LOG.info("Created producer destination: " + producerDestination + " of type: " + producerDestination.getClass());
|
||||
producer = session.createProducer(producerDestination);
|
||||
producer.setDeliveryMode(deliveryMode);
|
||||
|
||||
LOG.info("Created producer: " + producer + " delivery mode = " + (deliveryMode == DeliveryMode.PERSISTENT ? "PERSISTENT" : "NON_PERSISTENT"));
|
||||
connection.start();
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
session.close();
|
||||
connection.close();
|
||||
}
|
||||
|
||||
protected MessageConsumer createConsumer(String selector) throws JMSException {
|
||||
if (durable) {
|
||||
LOG.info("Creating durable consumer");
|
||||
return session.createDurableSubscriber((Topic)consumerDestination, getName(), selector, false);
|
||||
}
|
||||
return session.createConsumer(consumerDestination, selector);
|
||||
}
|
||||
|
||||
public void sendMessages() throws Exception {
|
||||
TextMessage message = session.createTextMessage("1");
|
||||
message.setIntProperty("id", 1);
|
||||
message.setJMSType("a");
|
||||
message.setStringProperty("stringProperty", "a");
|
||||
message.setLongProperty("longProperty", 1);
|
||||
message.setBooleanProperty("booleanProperty", true);
|
||||
producer.send(message);
|
||||
|
||||
message = session.createTextMessage("2");
|
||||
message.setIntProperty("id", 2);
|
||||
message.setJMSType("a");
|
||||
message.setStringProperty("stringProperty", "a");
|
||||
message.setLongProperty("longProperty", 1);
|
||||
message.setBooleanProperty("booleanProperty", false);
|
||||
producer.send(message);
|
||||
|
||||
message = session.createTextMessage("3");
|
||||
message.setIntProperty("id", 3);
|
||||
message.setJMSType("a");
|
||||
message.setStringProperty("stringProperty", "a");
|
||||
message.setLongProperty("longProperty", 1);
|
||||
message.setBooleanProperty("booleanProperty", true);
|
||||
producer.send(message);
|
||||
|
||||
message = session.createTextMessage("4");
|
||||
message.setIntProperty("id", 4);
|
||||
message.setJMSType("b");
|
||||
message.setStringProperty("stringProperty", "b");
|
||||
message.setLongProperty("longProperty", 2);
|
||||
message.setBooleanProperty("booleanProperty", false);
|
||||
producer.send(message);
|
||||
|
||||
message = session.createTextMessage("5");
|
||||
message.setIntProperty("id", 5);
|
||||
message.setJMSType("c");
|
||||
message.setStringProperty("stringProperty", "c");
|
||||
message.setLongProperty("longProperty", 3);
|
||||
message.setBooleanProperty("booleanProperty", true);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
public void consumeMessages(int remaining) throws Exception {
|
||||
consumer = createConsumer(null);
|
||||
for (int i = 0; i < remaining; i++) {
|
||||
consumer.receive(1000);
|
||||
}
|
||||
consumer.close();
|
||||
|
||||
}
|
||||
|
||||
public void testEmptyPropertySelector() throws Exception {
|
||||
int remaining = 5;
|
||||
Message message = null;
|
||||
consumer = createConsumer("");
|
||||
sendMessages();
|
||||
while (true) {
|
||||
message = consumer.receive(1000);
|
||||
if (message == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
remaining--;
|
||||
}
|
||||
assertEquals(remaining, 0);
|
||||
consumer.close();
|
||||
consumeMessages(remaining);
|
||||
}
|
||||
|
||||
public void testPropertySelector() throws Exception {
|
||||
int remaining = 5;
|
||||
Message message = null;
|
||||
consumer = createConsumer("stringProperty = 'a' and longProperty = 1 and booleanProperty = true");
|
||||
sendMessages();
|
||||
while (true) {
|
||||
message = consumer.receive(1000);
|
||||
if (message == null) {
|
||||
break;
|
||||
}
|
||||
String text = ((TextMessage)message).getText();
|
||||
if (!text.equals("1") && !text.equals("3")) {
|
||||
fail("unexpected message: " + text);
|
||||
}
|
||||
remaining--;
|
||||
}
|
||||
assertEquals(remaining, 3);
|
||||
consumer.close();
|
||||
consumeMessages(remaining);
|
||||
|
||||
}
|
||||
|
||||
public void testJMSPropertySelector() throws Exception {
|
||||
int remaining = 5;
|
||||
Message message = null;
|
||||
consumer = createConsumer("JMSType = 'a' and stringProperty = 'a'");
|
||||
sendMessages();
|
||||
while (true) {
|
||||
message = consumer.receive(1000);
|
||||
if (message == null) {
|
||||
break;
|
||||
}
|
||||
String text = ((TextMessage)message).getText();
|
||||
if (!text.equals("1") && !text.equals("2") && !text.equals("3")) {
|
||||
fail("unexpected message: " + text);
|
||||
}
|
||||
remaining--;
|
||||
}
|
||||
assertEquals(remaining, 2);
|
||||
consumer.close();
|
||||
consumeMessages(remaining);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* 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.JMSException;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.Topic;
|
||||
import javax.jms.TopicSession;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsTopicSendReceiveSubscriberTest extends JmsTopicSendReceiveTest {
|
||||
protected MessageConsumer createConsumer() throws JMSException {
|
||||
if (durable) {
|
||||
return super.createConsumer();
|
||||
} else {
|
||||
TopicSession topicSession = (TopicSession)session;
|
||||
return topicSession.createSubscriber((Topic)consumerDestination, null, false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* 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.DeliveryMode;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.Topic;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsTopicSendReceiveTest extends JmsSendReceiveTestSupport {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JmsTopicSendReceiveTest.class);
|
||||
|
||||
protected Connection connection;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
connectionFactory = createConnectionFactory();
|
||||
connection = createConnection();
|
||||
if (durable) {
|
||||
connection.setClientID(getClass().getName());
|
||||
}
|
||||
|
||||
LOG.info("Created connection: " + connection);
|
||||
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
LOG.info("Created session: " + session);
|
||||
producer = session.createProducer(null);
|
||||
producer.setDeliveryMode(deliveryMode);
|
||||
|
||||
LOG.info("Created producer: " + producer + " delivery mode = " + (deliveryMode == DeliveryMode.PERSISTENT ? "PERSISTENT" : "NON_PERSISTENT"));
|
||||
|
||||
if (topic) {
|
||||
consumerDestination = session.createTopic(getConsumerSubject());
|
||||
producerDestination = session.createTopic(getProducerSubject());
|
||||
} else {
|
||||
consumerDestination = session.createQueue(getConsumerSubject());
|
||||
producerDestination = session.createQueue(getProducerSubject());
|
||||
}
|
||||
|
||||
LOG.info("Created consumer destination: " + consumerDestination + " of type: " + consumerDestination.getClass());
|
||||
LOG.info("Created producer destination: " + producerDestination + " of type: " + producerDestination.getClass());
|
||||
consumer = createConsumer();
|
||||
consumer.setMessageListener(this);
|
||||
connection.start();
|
||||
|
||||
// log.info("Created connection: " + connection);
|
||||
}
|
||||
|
||||
protected MessageConsumer createConsumer() throws JMSException {
|
||||
if (durable) {
|
||||
LOG.info("Creating durable consumer");
|
||||
return session.createDurableSubscriber((Topic)consumerDestination, getName());
|
||||
}
|
||||
return session.createConsumer(consumerDestination);
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
LOG.info("Dumping stats...");
|
||||
// connectionFactory.getStats().reset();
|
||||
|
||||
LOG.info("Closing down connection");
|
||||
|
||||
/** TODO we should be able to shut down properly */
|
||||
session.close();
|
||||
connection.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* 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.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.Session;
|
||||
|
||||
/**
|
||||
* @version
|
||||
*/
|
||||
public class JmsTopicSendReceiveWithTwoConnectionsTest extends JmsSendReceiveTestSupport {
|
||||
|
||||
private static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory
|
||||
.getLog(JmsTopicSendReceiveWithTwoConnectionsTest.class);
|
||||
|
||||
protected Connection sendConnection;
|
||||
protected Connection receiveConnection;
|
||||
protected Session receiveSession;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
connectionFactory = createConnectionFactory();
|
||||
|
||||
sendConnection = createSendConnection();
|
||||
sendConnection.start();
|
||||
|
||||
receiveConnection = createReceiveConnection();
|
||||
receiveConnection.start();
|
||||
|
||||
LOG.info("Created sendConnection: " + sendConnection);
|
||||
LOG.info("Created receiveConnection: " + receiveConnection);
|
||||
|
||||
session = createSendSession(sendConnection);
|
||||
receiveSession = createReceiveSession(receiveConnection);
|
||||
|
||||
LOG.info("Created sendSession: " + session);
|
||||
LOG.info("Created receiveSession: " + receiveSession);
|
||||
|
||||
producer = session.createProducer(null);
|
||||
producer.setDeliveryMode(deliveryMode);
|
||||
|
||||
LOG.info("Created producer: " + producer + " delivery mode = "
|
||||
+ (deliveryMode == DeliveryMode.PERSISTENT ? "PERSISTENT" : "NON_PERSISTENT"));
|
||||
|
||||
if (topic) {
|
||||
consumerDestination = session.createTopic(getConsumerSubject());
|
||||
producerDestination = session.createTopic(getProducerSubject());
|
||||
} else {
|
||||
consumerDestination = session.createQueue(getConsumerSubject());
|
||||
producerDestination = session.createQueue(getProducerSubject());
|
||||
}
|
||||
|
||||
LOG.info("Created consumer destination: " + consumerDestination + " of type: "
|
||||
+ consumerDestination.getClass());
|
||||
LOG.info("Created producer destination: " + producerDestination + " of type: "
|
||||
+ producerDestination.getClass());
|
||||
|
||||
consumer = createConsumer(receiveSession, consumerDestination);
|
||||
consumer.setMessageListener(this);
|
||||
|
||||
LOG.info("Started connections");
|
||||
}
|
||||
|
||||
protected Session createReceiveSession(Connection receiveConnection) throws Exception {
|
||||
return receiveConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
}
|
||||
|
||||
protected Session createSendSession(Connection sendConnection) throws Exception {
|
||||
return sendConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
}
|
||||
|
||||
protected Connection createReceiveConnection() throws Exception {
|
||||
return createConnection();
|
||||
}
|
||||
|
||||
protected Connection createSendConnection() throws Exception {
|
||||
return createConnection();
|
||||
}
|
||||
|
||||
protected MessageConsumer createConsumer(Session session, Destination dest) throws JMSException {
|
||||
return session.createConsumer(dest);
|
||||
}
|
||||
|
||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
session.close();
|
||||
receiveSession.close();
|
||||
sendConnection.close();
|
||||
receiveConnection.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JmsTopicSendReceiveWithTwoConnectionsWithJMXTest extends
|
||||
JmsTopicSendReceiveWithTwoConnectionsTest {
|
||||
|
||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false&broker.useJmx=true");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* 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.TextMessage;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsTopicSendSameMessageTest extends JmsTopicSendReceiveWithTwoConnectionsTest {
|
||||
|
||||
private static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory
|
||||
.getLog(JmsTopicSendSameMessageTest.class);
|
||||
|
||||
public void testSendReceive() throws Exception {
|
||||
messages.clear();
|
||||
|
||||
TextMessage message = session.createTextMessage();
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
message.setText(data[i]);
|
||||
message.setStringProperty("stringProperty", data[i]);
|
||||
message.setIntProperty("intProperty", i);
|
||||
|
||||
if (verbose) {
|
||||
LOG.info("About to send a message: " + message + " with text: " + data[i]);
|
||||
}
|
||||
|
||||
producer.send(producerDestination, message);
|
||||
}
|
||||
|
||||
assertMessagesAreReceived();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* 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 org.apache.activemq.test.JmsResourceProvider;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsTopicTransactionTest extends JmsTransactionTestSupport {
|
||||
|
||||
/**
|
||||
* @see org.apache.activemq.JmsTransactionTestSupport#getJmsResourceProvider()
|
||||
*/
|
||||
protected JmsResourceProvider getJmsResourceProvider() {
|
||||
JmsResourceProvider p = new JmsResourceProvider();
|
||||
p.setTopic(true);
|
||||
p.setDurableName("testsub");
|
||||
p.setClientID("testclient");
|
||||
return p;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
/**
|
||||
* 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.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.test.JmsTopicSendReceiveTest;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsTopicWildcardSendReceiveTest extends JmsTopicSendReceiveTest {
|
||||
|
||||
private String destination1String = "TEST.ONE.ONE";
|
||||
private String destination2String = "TEST.ONE.ONE.ONE";
|
||||
private String destination3String = "TEST.ONE.TWO";
|
||||
private String destination4String = "TEST.TWO.ONE";
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
topic = true;
|
||||
durable = false;
|
||||
deliveryMode = DeliveryMode.NON_PERSISTENT;
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
protected String getConsumerSubject() {
|
||||
return "FOO.>";
|
||||
}
|
||||
|
||||
protected String getProducerSubject() {
|
||||
return "FOO.BAR.HUMBUG";
|
||||
}
|
||||
|
||||
public void testReceiveWildcardTopicEndAsterisk() throws Exception {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
ActiveMQDestination destination1 = (ActiveMQDestination)session.createTopic(destination1String);
|
||||
ActiveMQDestination destination3 = (ActiveMQDestination)session.createTopic(destination3String);
|
||||
|
||||
Message m = null;
|
||||
MessageConsumer consumer = null;
|
||||
String text = null;
|
||||
|
||||
ActiveMQDestination destination6 = (ActiveMQDestination)session.createTopic("TEST.ONE.*");
|
||||
consumer = session.createConsumer(destination6);
|
||||
sendMessage(session, destination1, destination1String);
|
||||
sendMessage(session, destination3, destination3String);
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
text = ((TextMessage)m).getText();
|
||||
if (!(text.equals(destination1String) || text.equals(destination3String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
text = ((TextMessage)m).getText();
|
||||
if (!(text.equals(destination1String) || text.equals(destination3String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void testReceiveWildcardTopicEndGreaterThan() throws Exception {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
ActiveMQDestination destination1 = (ActiveMQDestination)session.createTopic(destination1String);
|
||||
ActiveMQDestination destination2 = (ActiveMQDestination)session.createTopic(destination2String);
|
||||
ActiveMQDestination destination3 = (ActiveMQDestination)session.createTopic(destination3String);
|
||||
|
||||
Message m = null;
|
||||
MessageConsumer consumer = null;
|
||||
String text = null;
|
||||
|
||||
ActiveMQDestination destination7 = (ActiveMQDestination)session.createTopic("TEST.ONE.>");
|
||||
consumer = session.createConsumer(destination7);
|
||||
sendMessage(session, destination1, destination1String);
|
||||
sendMessage(session, destination2, destination2String);
|
||||
sendMessage(session, destination3, destination3String);
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
text = ((TextMessage)m).getText();
|
||||
if (!(text.equals(destination1String) || text.equals(destination2String) || text.equals(destination3String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
if (!(text.equals(destination1String) || text.equals(destination2String) || text.equals(destination3String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
if (!(text.equals(destination1String) || text.equals(destination2String) || text.equals(destination3String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void testReceiveWildcardTopicMidAsterisk() throws Exception {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
ActiveMQDestination destination1 = (ActiveMQDestination)session.createTopic(destination1String);
|
||||
ActiveMQDestination destination4 = (ActiveMQDestination)session.createTopic(destination4String);
|
||||
|
||||
Message m = null;
|
||||
MessageConsumer consumer = null;
|
||||
String text = null;
|
||||
|
||||
ActiveMQDestination destination8 = (ActiveMQDestination)session.createTopic("TEST.*.ONE");
|
||||
consumer = session.createConsumer(destination8);
|
||||
sendMessage(session, destination1, destination1String);
|
||||
sendMessage(session, destination4, destination4String);
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
text = ((TextMessage)m).getText();
|
||||
if (!(text.equals(destination1String) || text.equals(destination4String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
text = ((TextMessage)m).getText();
|
||||
if (!(text.equals(destination1String) || text.equals(destination4String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
assertNull(consumer.receiveNoWait());
|
||||
|
||||
}
|
||||
|
||||
public void testReceiveWildcardTopicMatchDoubleWildcard() throws Exception {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
ActiveMQDestination destination1 = (ActiveMQDestination)session.createTopic("a.*.>.>");
|
||||
ActiveMQDestination destination2 = (ActiveMQDestination)session.createTopic("a.b");
|
||||
|
||||
Message m = null;
|
||||
MessageConsumer consumer = null;
|
||||
String text = null;
|
||||
|
||||
|
||||
consumer = session.createConsumer(destination1);
|
||||
sendMessage(session, destination2, destination3String);
|
||||
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
text = ((TextMessage)m).getText();
|
||||
if (!(text.equals(destination1String) || text.equals(destination3String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
public void testReceiveWildcardTopicMatchSinglePastTheEndWildcard() throws Exception {
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
ActiveMQDestination destination1 = (ActiveMQDestination)session.createTopic("a.>");
|
||||
ActiveMQDestination destination2 = (ActiveMQDestination)session.createTopic("a");
|
||||
|
||||
Message m = null;
|
||||
MessageConsumer consumer = null;
|
||||
String text = null;
|
||||
|
||||
|
||||
consumer = session.createConsumer(destination1);
|
||||
sendMessage(session, destination2, destination3String);
|
||||
|
||||
m = consumer.receive(1000);
|
||||
assertNotNull(m);
|
||||
text = ((TextMessage)m).getText();
|
||||
if (!(text.equals(destination1String) || text.equals(destination3String))) {
|
||||
fail("unexpected message:" + text);
|
||||
}
|
||||
|
||||
assertNull(consumer.receiveNoWait());
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void sendMessage(Session session, Destination destination, String text) throws JMSException {
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.send(session.createTextMessage(text));
|
||||
producer.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
/**
|
||||
* 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.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
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.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.Topic;
|
||||
|
||||
import org.apache.activemq.command.ActiveMQMessage;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.util.IdGenerator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class LargeMessageTestSupport extends ClientTestSupport implements MessageListener {
|
||||
|
||||
protected static final int LARGE_MESSAGE_SIZE = 128 * 1024;
|
||||
protected static final int MESSAGE_COUNT = 100;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LargeMessageTestSupport.class);
|
||||
|
||||
protected Connection producerConnection;
|
||||
protected Connection consumerConnection;
|
||||
protected MessageConsumer consumer;
|
||||
protected MessageProducer producer;
|
||||
protected Session producerSession;
|
||||
protected Session consumerSession;
|
||||
protected byte[] largeMessageData;
|
||||
protected Destination destination;
|
||||
protected boolean isTopic = true;
|
||||
protected boolean isDurable = true;
|
||||
protected int deliveryMode = DeliveryMode.PERSISTENT;
|
||||
protected IdGenerator idGen = new IdGenerator();
|
||||
protected boolean validMessageConsumption = true;
|
||||
protected AtomicInteger messageCount = new AtomicInteger(0);
|
||||
|
||||
protected int prefetchValue = 10000000;
|
||||
|
||||
protected Destination createDestination() {
|
||||
String subject = getClass().getName();
|
||||
if (isTopic) {
|
||||
return new ActiveMQTopic(subject);
|
||||
} else {
|
||||
return new ActiveMQQueue(subject);
|
||||
}
|
||||
}
|
||||
|
||||
protected MessageConsumer createConsumer() throws JMSException {
|
||||
if (isTopic && isDurable) {
|
||||
return consumerSession.createDurableSubscriber((Topic)destination, idGen.generateId());
|
||||
} else {
|
||||
return consumerSession.createConsumer(destination);
|
||||
}
|
||||
}
|
||||
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
ClientTestSupport.removeMessageStore();
|
||||
LOG.info("Setting up . . . . . ");
|
||||
messageCount.set(0);
|
||||
|
||||
destination = createDestination();
|
||||
largeMessageData = new byte[LARGE_MESSAGE_SIZE];
|
||||
for (int i = 0; i < LARGE_MESSAGE_SIZE; i++) {
|
||||
if (i % 2 == 0) {
|
||||
largeMessageData[i] = 'a';
|
||||
} else {
|
||||
largeMessageData[i] = 'z';
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// allow the broker to start
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new JMSException(e.getMessage());
|
||||
}
|
||||
|
||||
ActiveMQConnectionFactory fac = getConnectionFactory();
|
||||
producerConnection = fac.createConnection();
|
||||
setPrefetchPolicy((ActiveMQConnection)producerConnection);
|
||||
producerConnection.start();
|
||||
|
||||
consumerConnection = fac.createConnection();
|
||||
setPrefetchPolicy((ActiveMQConnection)consumerConnection);
|
||||
consumerConnection.setClientID(idGen.generateId());
|
||||
consumerConnection.start();
|
||||
producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
producer = producerSession.createProducer(createDestination());
|
||||
producer.setDeliveryMode(deliveryMode);
|
||||
consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
consumer = createConsumer();
|
||||
consumer.setMessageListener(this);
|
||||
LOG.info("Setup complete");
|
||||
}
|
||||
|
||||
protected void setPrefetchPolicy(ActiveMQConnection activeMQConnection) {
|
||||
activeMQConnection.getPrefetchPolicy().setTopicPrefetch(prefetchValue);
|
||||
activeMQConnection.getPrefetchPolicy().setQueuePrefetch(prefetchValue);
|
||||
activeMQConnection.getPrefetchPolicy().setDurableTopicPrefetch(prefetchValue);
|
||||
activeMQConnection.getPrefetchPolicy().setQueueBrowserPrefetch(prefetchValue);
|
||||
activeMQConnection.getPrefetchPolicy().setOptimizeDurableTopicPrefetch(prefetchValue);
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
Thread.sleep(1000);
|
||||
producerConnection.close();
|
||||
consumerConnection.close();
|
||||
|
||||
super.tearDown();
|
||||
|
||||
largeMessageData = null;
|
||||
}
|
||||
|
||||
protected boolean isSame(BytesMessage msg1) throws Exception {
|
||||
boolean result = false;
|
||||
((ActiveMQMessage)msg1).setReadOnlyBody(true);
|
||||
|
||||
for (int i = 0; i < LARGE_MESSAGE_SIZE; i++) {
|
||||
result = msg1.readByte() == largeMessageData[i];
|
||||
if (!result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void onMessage(Message msg) {
|
||||
try {
|
||||
BytesMessage ba = (BytesMessage)msg;
|
||||
validMessageConsumption &= isSame(ba);
|
||||
assertTrue(ba.getBodyLength() == LARGE_MESSAGE_SIZE);
|
||||
if (messageCount.incrementAndGet() >= MESSAGE_COUNT) {
|
||||
synchronized (messageCount) {
|
||||
messageCount.notify();
|
||||
}
|
||||
}
|
||||
LOG.info("got message = " + messageCount);
|
||||
if (messageCount.get() % 50 == 0) {
|
||||
LOG.info("count = " + messageCount);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void testLargeMessages() throws Exception {
|
||||
for (int i = 0; i < MESSAGE_COUNT; i++) {
|
||||
LOG.info("Sending message: " + i);
|
||||
BytesMessage msg = producerSession.createBytesMessage();
|
||||
msg.writeBytes(largeMessageData);
|
||||
producer.send(msg);
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
while (now + 60000 > System.currentTimeMillis() && messageCount.get() < MESSAGE_COUNT) {
|
||||
LOG.info("message count = " + messageCount);
|
||||
synchronized (messageCount) {
|
||||
messageCount.wait(1000);
|
||||
}
|
||||
}
|
||||
LOG.info("Finished count = " + messageCount);
|
||||
assertTrue("Not enough messages - expected " + MESSAGE_COUNT + " but got " + messageCount, messageCount.get() == MESSAGE_COUNT);
|
||||
assertTrue("received messages are not valid", validMessageConsumption);
|
||||
Thread.sleep(1000);
|
||||
LOG.info("FINAL count = " + messageCount);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author rnewson
|
||||
*/
|
||||
public final class LargeStreamletTest extends TestCase {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LargeStreamletTest.class);
|
||||
private static final String BROKER_URL = "vm://localhost?broker.persistent=false";
|
||||
private static final int BUFFER_SIZE = 1 * 1024;
|
||||
private static final int MESSAGE_COUNT = 10 * 1024;
|
||||
|
||||
protected Exception writerException;
|
||||
protected Exception readerException;
|
||||
|
||||
private final AtomicInteger totalRead = new AtomicInteger();
|
||||
private final AtomicInteger totalWritten = new AtomicInteger();
|
||||
private final AtomicBoolean stopThreads = new AtomicBoolean(false);
|
||||
|
||||
public void testStreamlets() throws Exception {
|
||||
final ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(BROKER_URL);
|
||||
|
||||
final ActiveMQConnection connection = (ActiveMQConnection)factory.createConnection();
|
||||
connection.start();
|
||||
try {
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
try {
|
||||
final Destination destination = session.createQueue("wibble");
|
||||
final Thread readerThread = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
totalRead.set(0);
|
||||
try {
|
||||
final InputStream inputStream = connection.createInputStream(destination);
|
||||
try {
|
||||
int read;
|
||||
final byte[] buf = new byte[BUFFER_SIZE];
|
||||
while (!stopThreads.get() && (read = inputStream.read(buf)) != -1) {
|
||||
totalRead.addAndGet(read);
|
||||
}
|
||||
} finally {
|
||||
inputStream.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
readerException = e;
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
LOG.info(totalRead + " total bytes read.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final Thread writerThread = new Thread(new Runnable() {
|
||||
private final Random random = new Random();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
totalWritten.set(0);
|
||||
int count = MESSAGE_COUNT;
|
||||
try {
|
||||
final OutputStream outputStream = connection.createOutputStream(destination);
|
||||
try {
|
||||
final byte[] buf = new byte[BUFFER_SIZE];
|
||||
random.nextBytes(buf);
|
||||
while (count > 0 && !stopThreads.get()) {
|
||||
outputStream.write(buf);
|
||||
totalWritten.addAndGet(buf.length);
|
||||
count--;
|
||||
}
|
||||
} finally {
|
||||
outputStream.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
writerException = e;
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
LOG.info(totalWritten + " total bytes written.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
readerThread.start();
|
||||
writerThread.start();
|
||||
|
||||
// Wait till reader is has finished receiving all the messages
|
||||
// or he has stopped
|
||||
// receiving messages.
|
||||
Thread.sleep(1000);
|
||||
int lastRead = totalRead.get();
|
||||
while (readerThread.isAlive()) {
|
||||
readerThread.join(1000);
|
||||
// No progress?? then stop waiting..
|
||||
if (lastRead == totalRead.get()) {
|
||||
break;
|
||||
}
|
||||
lastRead = totalRead.get();
|
||||
}
|
||||
|
||||
stopThreads.set(true);
|
||||
|
||||
assertTrue("Should not have received a reader exception", readerException == null);
|
||||
assertTrue("Should not have received a writer exception", writerException == null);
|
||||
|
||||
assertEquals("Not all messages accounted for", totalWritten.get(), totalRead.get());
|
||||
|
||||
} finally {
|
||||
session.close();
|
||||
}
|
||||
} finally {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
/**
|
||||
* 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.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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 junit.framework.Test;
|
||||
import org.apache.activemq.broker.BrokerFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.TransportConnector;
|
||||
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);
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
LOG.info("Start: " + getName());
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
protected ConnectionFactory createConnectionFactory() throws URISyntaxException, IOException {
|
||||
return new ActiveMQConnectionFactory(((TransportConnector)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() {
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,288 @@
|
|||
/**
|
||||
* 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 static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
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.Topic;
|
||||
|
||||
import org.apache.activemq.advisory.AdvisorySupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.region.policy.ConstantPendingMessageLimitStrategy;
|
||||
import org.apache.activemq.broker.region.policy.FilePendingSubscriberMessageStoragePolicy;
|
||||
import org.apache.activemq.broker.region.policy.OldestMessageEvictionStrategy;
|
||||
import org.apache.activemq.broker.region.policy.PendingSubscriberMessageStoragePolicy;
|
||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
||||
import org.apache.activemq.broker.region.policy.VMPendingSubscriberMessageStoragePolicy;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ActiveMQMessage;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.util.Wait;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MessageEvictionTest {
|
||||
static final Logger LOG = LoggerFactory.getLogger(MessageEvictionTest.class);
|
||||
private BrokerService broker;
|
||||
private ConnectionFactory connectionFactory;
|
||||
Connection connection;
|
||||
private Session session;
|
||||
private Topic destination;
|
||||
private final String destinationName = "verifyEvection";
|
||||
protected int numMessages = 2000;
|
||||
protected String payload = new String(new byte[1024*2]);
|
||||
|
||||
public void setUp(PendingSubscriberMessageStoragePolicy pendingSubscriberPolicy) throws Exception {
|
||||
broker = createBroker(pendingSubscriberPolicy);
|
||||
broker.start();
|
||||
connectionFactory = createConnectionFactory();
|
||||
connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
destination = session.createTopic(destinationName);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
connection.stop();
|
||||
broker.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageEvictionMemoryUsageFileCursor() throws Exception {
|
||||
setUp(new FilePendingSubscriberMessageStoragePolicy());
|
||||
doTestMessageEvictionMemoryUsage();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageEvictionMemoryUsageVmCursor() throws Exception {
|
||||
setUp(new VMPendingSubscriberMessageStoragePolicy());
|
||||
doTestMessageEvictionMemoryUsage();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageEvictionDiscardedAdvisory() throws Exception {
|
||||
setUp(new VMPendingSubscriberMessageStoragePolicy());
|
||||
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
final CountDownLatch consumerRegistered = new CountDownLatch(1);
|
||||
final CountDownLatch gotAdvisory = new CountDownLatch(1);
|
||||
final CountDownLatch advisoryIsGood = new CountDownLatch(1);
|
||||
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ActiveMQTopic discardedAdvisoryDestination =
|
||||
AdvisorySupport.getMessageDiscardedAdvisoryTopic(destination);
|
||||
// use separate session rather than asyncDispatch on consumer session
|
||||
// as we want consumer session to block
|
||||
Session advisorySession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final MessageConsumer consumer = advisorySession.createConsumer(discardedAdvisoryDestination);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
int advisoriesReceived = 0;
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
try {
|
||||
LOG.info("advisory:" + message);
|
||||
ActiveMQMessage activeMQMessage = (ActiveMQMessage) message;
|
||||
assertNotNull(activeMQMessage.getStringProperty(AdvisorySupport.MSG_PROPERTY_CONSUMER_ID));
|
||||
assertEquals(++advisoriesReceived, activeMQMessage.getIntProperty(AdvisorySupport.MSG_PROPERTY_DISCARDED_COUNT));
|
||||
message.acknowledge();
|
||||
advisoryIsGood.countDown();
|
||||
} catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
} finally {
|
||||
gotAdvisory.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
consumerRegistered.countDown();
|
||||
gotAdvisory.await(120, TimeUnit.SECONDS);
|
||||
consumer.close();
|
||||
advisorySession.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
assertTrue("we have an advisory consumer", consumerRegistered.await(60, TimeUnit.SECONDS));
|
||||
doTestMessageEvictionMemoryUsage();
|
||||
assertTrue("got an advisory for discarded", gotAdvisory.await(0, TimeUnit.SECONDS));
|
||||
assertTrue("advisory is good",advisoryIsGood.await(0, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
public void doTestMessageEvictionMemoryUsage() throws Exception {
|
||||
|
||||
ExecutorService executor = Executors.newCachedThreadPool();
|
||||
final CountDownLatch doAck = new CountDownLatch(1);
|
||||
final CountDownLatch ackDone = new CountDownLatch(1);
|
||||
final CountDownLatch consumerRegistered = new CountDownLatch(1);
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final MessageConsumer consumer = session.createConsumer(destination);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
try {
|
||||
// very slow, only ack once
|
||||
doAck.await(60, TimeUnit.SECONDS);
|
||||
LOG.info("acking: " + message.getJMSMessageID());
|
||||
message.acknowledge();
|
||||
ackDone.countDown();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
} finally {
|
||||
consumerRegistered.countDown();
|
||||
ackDone.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
consumerRegistered.countDown();
|
||||
ackDone.await(60, TimeUnit.SECONDS);
|
||||
consumer.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue("we have a consumer", consumerRegistered.await(10, TimeUnit.SECONDS));
|
||||
|
||||
final AtomicInteger sent = new AtomicInteger(0);
|
||||
final CountDownLatch sendDone = new CountDownLatch(1);
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MessageProducer producer;
|
||||
try {
|
||||
producer = session.createProducer(destination);
|
||||
for (int i=0; i< numMessages; i++) {
|
||||
producer.send(session.createTextMessage(payload));
|
||||
sent.incrementAndGet();
|
||||
TimeUnit.MILLISECONDS.sleep(10);
|
||||
}
|
||||
producer.close();
|
||||
sendDone.countDown();
|
||||
} catch (Exception e) {
|
||||
sendDone.countDown();
|
||||
e.printStackTrace();
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue("messages sending done", sendDone.await(180, TimeUnit.SECONDS));
|
||||
assertEquals("all message were sent", numMessages, sent.get());
|
||||
|
||||
doAck.countDown();
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(30, TimeUnit.SECONDS);
|
||||
|
||||
assertTrue("usage goes to 0 once consumer goes away", Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return 0 == TestSupport.getDestination(broker,
|
||||
ActiveMQDestination.transform(destination)).getMemoryUsage().getPercentUsage();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
BrokerService createBroker(PendingSubscriberMessageStoragePolicy pendingSubscriberPolicy) throws Exception {
|
||||
BrokerService brokerService = new BrokerService();
|
||||
brokerService.addConnector("tcp://localhost:0");
|
||||
brokerService.setUseJmx(false);
|
||||
brokerService.setDeleteAllMessagesOnStartup(true);
|
||||
|
||||
// spooling to disk early so topic memory limit is not reached
|
||||
brokerService.getSystemUsage().getMemoryUsage().setLimit(500*1024);
|
||||
|
||||
final List<PolicyEntry> policyEntries = new ArrayList<PolicyEntry>();
|
||||
final PolicyEntry entry = new PolicyEntry();
|
||||
entry.setTopic(">");
|
||||
|
||||
entry.setAdvisoryForDiscardingMessages(true);
|
||||
|
||||
// so consumer does not get over run while blocked limit the prefetch
|
||||
entry.setTopicPrefetch(50);
|
||||
|
||||
|
||||
entry.setPendingSubscriberPolicy(pendingSubscriberPolicy);
|
||||
|
||||
// limit the number of outstanding messages, large enough to use the file store
|
||||
// or small enough not to blow memory limit
|
||||
int pendingMessageLimit = 50;
|
||||
if (pendingSubscriberPolicy instanceof FilePendingSubscriberMessageStoragePolicy) {
|
||||
pendingMessageLimit = 500;
|
||||
}
|
||||
ConstantPendingMessageLimitStrategy pendingMessageLimitStrategy = new ConstantPendingMessageLimitStrategy();
|
||||
pendingMessageLimitStrategy.setLimit(pendingMessageLimit);
|
||||
entry.setPendingMessageLimitStrategy(pendingMessageLimitStrategy);
|
||||
|
||||
// to keep the limit in check and up to date rather than just the first few, evict some
|
||||
OldestMessageEvictionStrategy messageEvictionStrategy = new OldestMessageEvictionStrategy();
|
||||
// whether to check expiry before eviction, default limit 1000 is fine as no ttl set in this test
|
||||
//messageEvictionStrategy.setEvictExpiredMessagesHighWatermark(1000);
|
||||
entry.setMessageEvictionStrategy(messageEvictionStrategy);
|
||||
|
||||
// let evicted messaged disappear
|
||||
entry.setDeadLetterStrategy(null);
|
||||
policyEntries.add(entry);
|
||||
|
||||
final PolicyMap policyMap = new PolicyMap();
|
||||
policyMap.setPolicyEntries(policyEntries);
|
||||
brokerService.setDestinationPolicy(policyMap);
|
||||
|
||||
return brokerService;
|
||||
}
|
||||
|
||||
ConnectionFactory createConnectionFactory() throws Exception {
|
||||
String url = broker.getTransportConnectors().get(0).getServer().getConnectURI().toString();
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(url);
|
||||
factory.setWatchTopicAdvisories(false);
|
||||
return factory;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue