ARTEMIS-463 Improvement to the openwire testsuite
https://issues.apache.org/jira/browse/ARTEMIS-463 This was a team effort from Clebert Suconic and Howard Gao
This commit is contained in:
parent
7e80cc3586
commit
2e66673048
|
@ -29,7 +29,7 @@
|
|||
|
||||
<properties>
|
||||
<activemq.basedir>${project.basedir}/../..</activemq.basedir>
|
||||
<activemq5.project.version>5.11.1</activemq5.project.version>
|
||||
<activemq5.project.version>5.12.0</activemq5.project.version>
|
||||
<jmdns-version>3.4.1</jmdns-version>
|
||||
<ftpserver-version>1.0.6</ftpserver-version>
|
||||
<jmock-version>2.5.1</jmock-version>
|
||||
|
@ -43,11 +43,20 @@
|
|||
<jasypt-version>1.9.2</jasypt-version>
|
||||
<directory-version>2.0.0-M6</directory-version>
|
||||
<activeio-core-version>3.1.4</activeio-core-version>
|
||||
<byteman.version>2.2.0</byteman.version>
|
||||
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- I imported this to get the ThreadLeakCheck -->
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>artemis-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-client</artifactId>
|
||||
|
@ -60,13 +69,6 @@
|
|||
<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>
|
||||
|
@ -313,6 +315,47 @@
|
|||
<artifactId>artemis-openwire-protocol</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.byteman</groupId>
|
||||
<artifactId>byteman</artifactId>
|
||||
<version>${byteman.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.byteman</groupId>
|
||||
<artifactId>byteman-submit</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>${byteman.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.byteman</groupId>
|
||||
<artifactId>byteman-install</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>${byteman.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.byteman</groupId>
|
||||
<artifactId>byteman-bmunit</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>${byteman.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
JBoss Logging
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logmanager</groupId>
|
||||
<artifactId>jboss-logmanager</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
@ -382,11 +425,13 @@
|
|||
<configuration>
|
||||
<skipTests>${skipActiveMQ5Tests}</skipTests>
|
||||
<includes>
|
||||
<!-- include this first three packages -->
|
||||
<!-- included packages -->
|
||||
<include>**/org/apache/activemq/*Test.java</include>
|
||||
<include>**/org/apache/activemq/command/*Test.java</include>
|
||||
<include>**/org/apache/activemq/openwire/*Test.java</include>
|
||||
<include>**/org/apache/activemq/transport/tcp/*Test.java</include>
|
||||
<include>**/org/apache/activemq/transport/failover/*Test.java</include>
|
||||
<include>**/org/apache/activemq/transport/*Test.java</include>
|
||||
<!-- tests that are known to pass-->
|
||||
<include>**/org/apache/activemq/blob/BlobTransferPolicyUriTest.java</include>
|
||||
</includes>
|
||||
|
@ -396,7 +441,6 @@
|
|||
<exclude>**/org/apache/activemq/ProducerFlowControlTest.java</exclude>
|
||||
<!-- exclude tests that are on client side only -->
|
||||
<exclude>**/org/apache/activemq/transport/tcp/TransportConnectorInvalidSocketOptionsTest.java</exclude>
|
||||
<exclude>**/org/apache/activemq/transport/tcp/TransportUriTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
|
|
@ -23,8 +23,11 @@ import java.net.URI;
|
|||
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ArtemisBrokerHelper {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ArtemisBrokerHelper.class);
|
||||
|
||||
private static volatile Object service = null;
|
||||
private static Class<?> serviceClass;
|
||||
|
@ -42,6 +45,7 @@ public class ArtemisBrokerHelper {
|
|||
// start a tcp transport artemis broker, the broker need to
|
||||
// be invm with client.
|
||||
public static void startArtemisBroker(URI location) throws IOException {
|
||||
LOG.info("---starting broker, service is there? " + service);
|
||||
if (service != null) {
|
||||
return;
|
||||
}
|
||||
|
@ -49,6 +53,7 @@ public class ArtemisBrokerHelper {
|
|||
service = serviceClass.newInstance();
|
||||
Method startMethod = serviceClass.getMethod("start");
|
||||
startMethod.invoke(service, (Object[]) null);
|
||||
LOG.info("started a service instance: " + service);
|
||||
}
|
||||
catch (InstantiationException e) {
|
||||
throw new IOException("Inst exception", e);
|
||||
|
@ -75,23 +80,21 @@ public class ArtemisBrokerHelper {
|
|||
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;
|
||||
}
|
||||
|
||||
public static BrokerService getBroker() {
|
||||
return (BrokerService) service;
|
||||
}
|
||||
|
||||
public static void stopArtemisBroker() throws Exception {
|
||||
public static void stopArtemisBroker() {
|
||||
try {
|
||||
if (service != null) {
|
||||
Method startMethod = serviceClass.getMethod("stop");
|
||||
startMethod.invoke(service, (Object[]) null);
|
||||
System.out.println("stopped the service instance: " + service);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
service = null;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/**
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* 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
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
|
@ -14,9 +14,19 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
public interface Receiver {
|
||||
package org.apache.activemq.broker;
|
||||
|
||||
void receive(String s) throws Exception;
|
||||
import org.apache.activemq.broker.artemiswrapper.ArtemisBrokerWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArtemisBrokerWrapperFactory {
|
||||
List<ArtemisBrokerWrapper> brokers = new ArrayList<>();
|
||||
|
||||
public static Broker createBroker(BrokerService brokerService) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -16,22 +16,26 @@
|
|||
*/
|
||||
package org.apache.activemq.broker;
|
||||
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionMetaData;
|
||||
import org.apache.activemq.Service;
|
||||
|
@ -44,10 +48,13 @@ import org.apache.activemq.broker.region.policy.PolicyMap;
|
|||
import org.apache.activemq.broker.scheduler.JobSchedulerStore;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.BrokerId;
|
||||
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.proxy.ProxyConnector;
|
||||
import org.apache.activemq.security.MessageAuthorizationPolicy;
|
||||
import org.apache.activemq.spring.SpringSslContext;
|
||||
import org.apache.activemq.store.PListStore;
|
||||
import org.apache.activemq.store.PersistenceAdapter;
|
||||
import org.apache.activemq.store.PersistenceAdapterFactory;
|
||||
|
@ -57,6 +64,7 @@ import org.apache.activemq.usage.SystemUsage;
|
|||
import org.apache.activemq.util.IOExceptionHandler;
|
||||
import org.apache.activemq.util.IOHelper;
|
||||
import org.apache.activemq.util.ServiceStopper;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -68,10 +76,12 @@ import org.slf4j.LoggerFactory;
|
|||
public class BrokerService implements Service {
|
||||
|
||||
public static final String DEFAULT_PORT = "61616";
|
||||
public static final AtomicInteger RANDOM_PORT_BASE = new AtomicInteger(51616);
|
||||
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 static boolean disableWrapper = false;
|
||||
|
||||
public String SERVER_SIDE_KEYSTORE;
|
||||
public String KEYSTORE_PASSWORD;
|
||||
|
@ -91,7 +101,7 @@ public class BrokerService implements Service {
|
|||
private BrokerId brokerId;
|
||||
private Throwable startException = null;
|
||||
private boolean startAsync = false;
|
||||
public Set<Integer> extraConnectors = new HashSet<>();
|
||||
public Set<ConnectorInfo> extraConnectors = new HashSet<>();
|
||||
|
||||
private List<TransportConnector> transportConnectors = new ArrayList<>();
|
||||
private File dataDirectoryFile;
|
||||
|
@ -99,6 +109,10 @@ public class BrokerService implements Service {
|
|||
private PolicyMap destinationPolicy;
|
||||
private SystemUsage systemUsage;
|
||||
|
||||
private final List<NetworkConnector> networkConnectors = new CopyOnWriteArrayList<NetworkConnector>();
|
||||
|
||||
private TemporaryFolder tmpfolder;
|
||||
|
||||
public static WeakHashMap<Broker, Exception> map = new WeakHashMap<>();
|
||||
|
||||
static {
|
||||
|
@ -117,7 +131,7 @@ public class BrokerService implements Service {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BrokerService[" + getBrokerName() + "]";
|
||||
return "BrokerService[" + getBrokerName() + "]" + super.toString();
|
||||
}
|
||||
|
||||
private String getBrokerVersion() {
|
||||
|
@ -131,6 +145,10 @@ public class BrokerService implements Service {
|
|||
|
||||
@Override
|
||||
public void start() throws Exception {
|
||||
File targetTmp = new File("./target/tmp");
|
||||
targetTmp.mkdirs();
|
||||
tmpfolder = new TemporaryFolder(targetTmp);
|
||||
tmpfolder.create();
|
||||
Exception e = new Exception();
|
||||
e.fillInStackTrace();
|
||||
startBroker(startAsync);
|
||||
|
@ -188,10 +206,10 @@ public class BrokerService implements Service {
|
|||
LOG.info("Apache ActiveMQ Artemis{} ({}, {}) is shutting down", new Object[]{getBrokerVersion(), getBrokerName(), brokerId});
|
||||
|
||||
if (broker != null) {
|
||||
System.out.println("______________________stopping broker: " + broker.getClass().getName());
|
||||
broker.stop();
|
||||
broker = null;
|
||||
}
|
||||
tmpfolder.delete();
|
||||
LOG.info("Apache ActiveMQ Artemis {} ({}, {}) is shutdown", new Object[]{getBrokerVersion(), getBrokerName(), brokerId});
|
||||
}
|
||||
|
||||
|
@ -200,7 +218,7 @@ public class BrokerService implements Service {
|
|||
|
||||
public Broker getBroker() throws Exception {
|
||||
if (broker == null) {
|
||||
broker = createBroker();
|
||||
broker = createBroker(tmpfolder.getRoot());
|
||||
}
|
||||
return broker;
|
||||
}
|
||||
|
@ -220,13 +238,13 @@ public class BrokerService implements Service {
|
|||
this.brokerName = str.trim();
|
||||
}
|
||||
|
||||
protected Broker createBroker() throws Exception {
|
||||
broker = createBrokerWrapper();
|
||||
protected Broker createBroker(File temporaryFile) throws Exception {
|
||||
broker = createBrokerWrapper(temporaryFile);
|
||||
return broker;
|
||||
}
|
||||
|
||||
private Broker createBrokerWrapper() {
|
||||
return new ArtemisBrokerWrapper(this);
|
||||
private Broker createBrokerWrapper(File temporaryFile) {
|
||||
return new ArtemisBrokerWrapper(this, temporaryFile);
|
||||
}
|
||||
|
||||
public void makeSureDestinationExists(ActiveMQDestination activemqDestination) throws Exception {
|
||||
|
@ -382,10 +400,6 @@ public class BrokerService implements Service {
|
|||
public void setKeepDurableSubsActive(boolean keepDurableSubsActive) {
|
||||
}
|
||||
|
||||
public NetworkConnector addNetworkConnector(String discoveryAddress) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
public TransportConnector getConnectorByName(String connectorName) {
|
||||
return null;
|
||||
}
|
||||
|
@ -407,8 +421,17 @@ public class BrokerService implements Service {
|
|||
public void setSchedulerDirectoryFile(File schedulerDirectory) {
|
||||
}
|
||||
|
||||
public NetworkConnector addNetworkConnector(String discoveryAddress) throws Exception {
|
||||
return addNetworkConnector(new URI(discoveryAddress));
|
||||
}
|
||||
|
||||
public NetworkConnector addNetworkConnector(URI discoveryAddress) throws Exception {
|
||||
NetworkConnector connector = new DiscoveryNetworkConnector(discoveryAddress);
|
||||
return addNetworkConnector(connector);
|
||||
}
|
||||
|
||||
public List<NetworkConnector> getNetworkConnectors() {
|
||||
return new ArrayList<>();
|
||||
return this.networkConnectors;
|
||||
}
|
||||
|
||||
public void setSchedulerSupport(boolean schedulerSupport) {
|
||||
|
@ -468,9 +491,53 @@ public class BrokerService implements Service {
|
|||
|
||||
public void setTransportConnectors(List<TransportConnector> transportConnectors) throws Exception {
|
||||
this.transportConnectors = transportConnectors;
|
||||
for (TransportConnector connector : transportConnectors) {
|
||||
if (connector.getUri().getScheme().equals("ssl")) {
|
||||
boolean added = this.extraConnectors.add(new ConnectorInfo(connector.getUri().getPort(), true));
|
||||
if (added) {
|
||||
System.out.println("added ssl connector " + connector);
|
||||
}
|
||||
else {
|
||||
System.out.println("WARNing! failed to add ssl connector: " + connector);
|
||||
}
|
||||
}
|
||||
else {
|
||||
boolean added = this.extraConnectors.add(new ConnectorInfo(connector.getUri().getPort()));
|
||||
if (added) {
|
||||
System.out.println("added connector " + connector);
|
||||
}
|
||||
else {
|
||||
System.out.println("WARNing! failed to add connector: " + connector);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public NetworkConnector addNetworkConnector(NetworkConnector connector) throws Exception {
|
||||
connector.setBrokerService(this);
|
||||
|
||||
System.out.println("------------------------ this broker uri: " + this.getConnectURI());
|
||||
connector.setLocalUri(this.getConnectURI());
|
||||
// Set a connection filter so that the connector does not establish loop
|
||||
// back connections.
|
||||
connector.setConnectionFilter(new ConnectionFilter() {
|
||||
@Override
|
||||
public boolean connectTo(URI location) {
|
||||
List<TransportConnector> transportConnectors = getTransportConnectors();
|
||||
for (Iterator<TransportConnector> iter = transportConnectors.iterator(); iter.hasNext();) {
|
||||
try {
|
||||
TransportConnector tc = iter.next();
|
||||
if (location.equals(tc.getConnectUri())) {
|
||||
return false;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
networkConnectors.add(connector);
|
||||
return connector;
|
||||
}
|
||||
|
||||
|
@ -486,19 +553,75 @@ public class BrokerService implements Service {
|
|||
|
||||
public TransportConnector addConnector(URI bindAddress) throws Exception {
|
||||
Integer port = bindAddress.getPort();
|
||||
String host = bindAddress.getHost();
|
||||
FakeTransportConnector connector = null;
|
||||
if (port != 0) {
|
||||
connector = new FakeTransportConnector(bindAddress);
|
||||
this.transportConnectors.add(connector);
|
||||
this.extraConnectors.add(port);
|
||||
|
||||
host = (host == null || host.length() == 0) ? "localhost" : host;
|
||||
if ("0.0.0.0".equals(host)) {
|
||||
host = "localhost";
|
||||
}
|
||||
else {
|
||||
connector = new FakeTransportConnector(new URI(this.getDefaultUri()));
|
||||
this.transportConnectors.add(connector);
|
||||
|
||||
if (port == 0) {
|
||||
//In actual impl in amq5, after connector has been added the socket
|
||||
//is bound already. This means in case of 0 port uri, the random
|
||||
//port is available after this call. With artemis wrapper however
|
||||
//the real binding happens during broker start. To work around this
|
||||
//we use manually calculated port for that.
|
||||
port = getPseudoRandomPort();
|
||||
|
||||
}
|
||||
|
||||
System.out.println("Now host is: " + host);
|
||||
bindAddress = new URI(bindAddress.getScheme(), bindAddress.getUserInfo(),
|
||||
host, port, bindAddress.getPath(), bindAddress.getQuery(), bindAddress.getFragment());
|
||||
|
||||
connector = new FakeTransportConnector(bindAddress);
|
||||
this.transportConnectors.add(connector);
|
||||
this.extraConnectors.add(new ConnectorInfo(port));
|
||||
|
||||
return connector;
|
||||
}
|
||||
|
||||
private int getPseudoRandomPort() {
|
||||
int port = RANDOM_PORT_BASE.getAndIncrement();
|
||||
int maxTry = 20;
|
||||
while (!checkPort(port)) {
|
||||
port = RANDOM_PORT_BASE.getAndIncrement();
|
||||
maxTry--;
|
||||
if (maxTry == 0) {
|
||||
LOG.error("Too many port used");
|
||||
break;
|
||||
}
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(5);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
public static boolean checkPort(final int port) {
|
||||
ServerSocket ssocket = null;
|
||||
try {
|
||||
ssocket = new ServerSocket(port);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info("port " + port + " is being used.");
|
||||
return false;
|
||||
}
|
||||
finally {
|
||||
if (ssocket != null) {
|
||||
try {
|
||||
ssocket.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setCacheTempDestinations(boolean cacheTempDestinations) {
|
||||
}
|
||||
|
||||
|
@ -607,6 +730,14 @@ public class BrokerService implements Service {
|
|||
|
||||
public void setSslContext(SslContext sslContext) {
|
||||
this.sslContext = sslContext;
|
||||
if (sslContext instanceof SpringSslContext) {
|
||||
SpringSslContext springContext = (SpringSslContext)sslContext;
|
||||
this.SERVER_SIDE_KEYSTORE = springContext.getKeyStore();
|
||||
this.KEYSTORE_PASSWORD = springContext.getKeyStorePassword();
|
||||
this.SERVER_SIDE_TRUSTSTORE = springContext.getTrustStore();
|
||||
this.TRUSTSTORE_PASSWORD = springContext.getTrustStorePassword();
|
||||
this.storeType = springContext.getKeyStoreType();
|
||||
}
|
||||
}
|
||||
|
||||
public void setPersistenceFactory(PersistenceAdapterFactory persistenceFactory) {
|
||||
|
@ -643,8 +774,10 @@ public class BrokerService implements Service {
|
|||
URI uri = null;
|
||||
try {
|
||||
if (this.extraConnectors.size() > 0) {
|
||||
Integer port = extraConnectors.iterator().next();
|
||||
uri = new URI("tcp://localhost:" + port);
|
||||
ConnectorInfo info = extraConnectors.iterator().next();
|
||||
Integer port = info.port;
|
||||
String schema = info.ssl ? "ssl" : "tcp";
|
||||
uri = new URI(schema + "://localhost:" + port);
|
||||
} else {
|
||||
uri = new URI(this.getDefaultUri());
|
||||
}
|
||||
|
@ -654,6 +787,33 @@ public class BrokerService implements Service {
|
|||
return uri;
|
||||
}
|
||||
|
||||
public static class ConnectorInfo {
|
||||
|
||||
public int port;
|
||||
public boolean ssl;
|
||||
|
||||
public ConnectorInfo(int port) {
|
||||
this(port, false);
|
||||
}
|
||||
|
||||
public ConnectorInfo(int port, boolean ssl) {
|
||||
this.port = port;
|
||||
this.ssl = ssl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ConnectorInfo) {
|
||||
return this.port == ((ConnectorInfo)obj).port;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
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;
|
||||
|
@ -65,7 +64,6 @@ 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;
|
||||
|
||||
|
@ -83,20 +81,19 @@ public abstract class ArtemisBrokerBase implements Broker {
|
|||
protected volatile boolean stopped;
|
||||
protected BrokerId brokerId = new BrokerId("Artemis Broker");
|
||||
protected BrokerService bservice;
|
||||
protected TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
protected String testDir;
|
||||
|
||||
protected final File temporaryFolder;
|
||||
protected final String testDir;
|
||||
protected boolean realStore = false;
|
||||
|
||||
protected ActiveMQServer server;
|
||||
|
||||
protected boolean enableSecurity = false;
|
||||
|
||||
public ArtemisBrokerBase() {
|
||||
try {
|
||||
this.temporaryFolder.create();
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
public ArtemisBrokerBase(File temporaryFolder) {
|
||||
this.temporaryFolder = temporaryFolder;
|
||||
this.testDir = temporaryFolder.getAbsolutePath();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.apache.activemq.broker.artemiswrapper;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
@ -28,40 +29,47 @@ 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.postoffice.Binding;
|
||||
import org.apache.activemq.artemis.core.registry.JndiBindingRegistry;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
|
||||
import org.apache.activemq.artemis.core.security.Role;
|
||||
import org.apache.activemq.artemis.core.server.impl.QueueImpl;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.apache.activemq.artemis.core.settings.impl.SlowConsumerPolicy;
|
||||
import org.apache.activemq.artemis.jms.server.impl.JMSServerManagerImpl;
|
||||
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManagerImpl;
|
||||
import org.apache.activemq.artemiswrapper.ArtemisBrokerHelper;
|
||||
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerFactory;
|
||||
|
||||
public class ArtemisBrokerWrapper extends ArtemisBrokerBase {
|
||||
|
||||
protected final Map<String, SimpleString> testQueues = new HashMap<>();
|
||||
protected JMSServerManagerImpl jmsServer;
|
||||
protected MBeanServer mbeanServer;
|
||||
|
||||
public ArtemisBrokerWrapper(BrokerService brokerService) {
|
||||
public ArtemisBrokerWrapper(BrokerService brokerService, File temporaryFolder) {
|
||||
super(temporaryFolder);
|
||||
this.bservice = brokerService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws Exception {
|
||||
testDir = temporaryFolder.getRoot().getAbsolutePath();
|
||||
clearDataRecreateServerDirs();
|
||||
|
||||
mbeanServer = MBeanServerFactory.createMBeanServer();
|
||||
|
||||
server = createServer(realStore, true);
|
||||
server.setMBeanServer(mbeanServer);
|
||||
|
||||
server.getConfiguration().getAcceptorConfigurations().clear();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put(TransportConstants.PORT_PROP_NAME, "61616");
|
||||
params.put(TransportConstants.PROTOCOLS_PROP_NAME, "OPENWIRE,CORE");
|
||||
TransportConfiguration transportConfiguration = new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params);
|
||||
|
||||
Configuration serverConfig = server.getConfiguration();
|
||||
serverConfig.setJMXManagementEnabled(true);
|
||||
|
||||
Map<String, AddressSettings> addressSettingsMap = serverConfig.getAddressesSettings();
|
||||
|
||||
|
@ -82,34 +90,16 @@ public class ArtemisBrokerWrapper extends ArtemisBrokerBase {
|
|||
commonSettings.setDeadLetterAddress(dla);
|
||||
commonSettings.setAutoCreateJmsQueues(true);
|
||||
|
||||
serverConfig.getAcceptorConfigurations().add(transportConfiguration);
|
||||
if (bservice.extraConnectors.size() == 0) {
|
||||
serverConfig.addAcceptorConfiguration("home", "tcp://localhost:61616?protocols=OPENWIRE,CORE");
|
||||
}
|
||||
if (this.bservice.enableSsl()) {
|
||||
params = new HashMap<>();
|
||||
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);
|
||||
//default
|
||||
addServerAcceptor(serverConfig, new BrokerService.ConnectorInfo(61611, true));
|
||||
}
|
||||
|
||||
for (Integer port : bservice.extraConnectors) {
|
||||
if (port.intValue() != 61616) {
|
||||
//extra port
|
||||
params = new HashMap<>();
|
||||
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);
|
||||
}
|
||||
for (BrokerService.ConnectorInfo info : bservice.extraConnectors) {
|
||||
addServerAcceptor(serverConfig, info);
|
||||
}
|
||||
|
||||
serverConfig.setSecurityEnabled(enableSecurity);
|
||||
|
@ -117,7 +107,7 @@ public class ArtemisBrokerWrapper extends ArtemisBrokerBase {
|
|||
//extraServerConfig(serverConfig);
|
||||
|
||||
if (enableSecurity) {
|
||||
ActiveMQSecurityManagerImpl sm = (ActiveMQSecurityManagerImpl) server.getSecurityManager();
|
||||
ActiveMQJAASSecurityManager sm = (ActiveMQJAASSecurityManager) server.getSecurityManager();
|
||||
SecurityConfiguration securityConfig = sm.getConfiguration();
|
||||
securityConfig.addRole("openwireSender", "sender");
|
||||
securityConfig.addUser("openwireSender", "SeNdEr");
|
||||
|
@ -170,16 +160,32 @@ public class ArtemisBrokerWrapper extends ArtemisBrokerBase {
|
|||
|
||||
server.start();
|
||||
|
||||
/*
|
||||
registerConnectionFactory();
|
||||
mbeanServer = MBeanServerFactory.createMBeanServer();
|
||||
*/
|
||||
|
||||
ArtemisBrokerHelper.setBroker(this.bservice);
|
||||
stopped = false;
|
||||
|
||||
}
|
||||
|
||||
private void addServerAcceptor(Configuration serverConfig, BrokerService.ConnectorInfo info) throws Exception {
|
||||
if (info.ssl) {
|
||||
HashMap<String, Object> params = new HashMap<String, Object>();
|
||||
params.put(TransportConstants.SSL_ENABLED_PROP_NAME, true);
|
||||
params.put(TransportConstants.PORT_PROP_NAME, info.port);
|
||||
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.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);
|
||||
}
|
||||
else {
|
||||
serverConfig.addAcceptorConfiguration("homePort" + info.port, "tcp://localhost:" + info.port + "?protocols=OPENWIRE,CORE");
|
||||
}
|
||||
}
|
||||
|
||||
private void translatePolicyMap(Configuration serverConfig, PolicyMap policyMap) {
|
||||
List allEntries = policyMap.getAllEntries();
|
||||
Map<String, AddressSettings> settingsMap = serverConfig.getAddressesSettings();
|
||||
|
@ -204,6 +210,8 @@ public class ArtemisBrokerWrapper extends ArtemisBrokerBase {
|
|||
settings.setAddressFullMessagePolicy(AddressFullMessagePolicy.FAIL);
|
||||
}
|
||||
}
|
||||
int queuePrefetch = entry.getQueuePrefetch();
|
||||
settings.setQueuePrefetch(queuePrefetch);
|
||||
}
|
||||
|
||||
PolicyEntry defaultEntry = policyMap.getDefaultEntry();
|
||||
|
@ -265,4 +273,19 @@ public class ArtemisBrokerWrapper extends ArtemisBrokerBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long getAMQueueMessageCount(String physicalName) {
|
||||
long count = 0;
|
||||
String qname = "jms.queue." + physicalName;
|
||||
Binding binding = server.getPostOffice().getBinding(new SimpleString(qname));
|
||||
if (binding != null) {
|
||||
QueueImpl q = (QueueImpl) binding.getBindable();
|
||||
count = q.getMessageCount();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public MBeanServer getMbeanServer() {
|
||||
return this.mbeanServer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.broker.artemiswrapper;
|
||||
|
||||
import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl;
|
||||
import org.apache.activemq.artemis.core.persistence.impl.journal.OperationContextImpl;
|
||||
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnector;
|
||||
import org.junit.rules.ExternalResource;
|
||||
|
||||
public class CleanupThreadRule extends ExternalResource {
|
||||
|
||||
@Override
|
||||
protected void before() throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void after() {
|
||||
OperationContextImpl.clearContext();
|
||||
|
||||
// We shutdown the global pools to give a better isolation between tests
|
||||
try {
|
||||
ServerLocatorImpl.clearThreadPools();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
NettyConnector.clearThreadPools();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
/**
|
||||
* 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.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.activemq.artemis.api.core.management.ObjectNameBuilder;
|
||||
import org.apache.activemq.artemis.api.jms.management.JMSQueueControl;
|
||||
import org.apache.activemq.artemis.api.jms.management.JMSServerControl;
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
|
||||
import org.apache.activemq.artemis.core.server.JournalType;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.JMSConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS;
|
||||
import org.apache.activemq.artemis.tests.util.ThreadLeakCheckRule;
|
||||
import org.apache.activemq.artemis.utils.uri.URISupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.rules.TestName;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerInvocationHandler;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
public class OpenwireArtemisBaseTest {
|
||||
@Rule
|
||||
public CleanupThreadRule cleanupRules = new CleanupThreadRule();
|
||||
|
||||
@Rule
|
||||
public ThreadLeakCheckRule leakCheckRule = new ThreadLeakCheckRule();
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder;
|
||||
@Rule
|
||||
public TestName name = new TestName();
|
||||
|
||||
public OpenwireArtemisBaseTest() {
|
||||
File tmpRoot = new File("./target/tmp");
|
||||
tmpRoot.mkdirs();
|
||||
temporaryFolder = new TemporaryFolder(tmpRoot);
|
||||
//The wrapper stuff will automatically create a default
|
||||
//server on a normal connection factory, which will
|
||||
//cause problems with clustering tests, which starts
|
||||
//all servers explicitly. Setting this to true
|
||||
//can prevent the auto-creation from happening.
|
||||
BrokerService.disableWrapper = true;
|
||||
}
|
||||
|
||||
|
||||
public String getTmp() {
|
||||
return getTmpFile().getAbsolutePath();
|
||||
}
|
||||
|
||||
public File getTmpFile() {
|
||||
return temporaryFolder.getRoot();
|
||||
}
|
||||
|
||||
protected String getJournalDir(int serverID, boolean backup) {
|
||||
return getTmp() + "/journal_" + serverID + "_" + backup;
|
||||
}
|
||||
|
||||
protected String getBindingsDir(int serverID, boolean backup) {
|
||||
return getTmp() + "/binding_" + serverID + "_" + backup;
|
||||
}
|
||||
|
||||
protected String getPageDir(int serverID, boolean backup) {
|
||||
return getTmp() + "/paging_" + serverID + "_" + backup;
|
||||
}
|
||||
|
||||
protected String getLargeMessagesDir(int serverID, boolean backup) {
|
||||
return getTmp() + "/paging_" + serverID + "_" + backup;
|
||||
}
|
||||
|
||||
public String CLUSTER_PASSWORD = "OPENWIRECLUSTER";
|
||||
|
||||
protected Configuration createConfig(final int serverID) throws Exception {
|
||||
return createConfig("localhost", serverID, Collections.EMPTY_MAP);
|
||||
}
|
||||
|
||||
protected Configuration createConfig(final String hostAddress, final int serverID, final int port) throws Exception {
|
||||
ConfigurationImpl configuration = new ConfigurationImpl().setJMXManagementEnabled(false).
|
||||
setSecurityEnabled(false).setJournalMinFiles(2).setJournalFileSize(1000 * 1024).setJournalType(JournalType.NIO).
|
||||
setJournalDirectory(getJournalDir(serverID, false)).
|
||||
setBindingsDirectory(getBindingsDir(serverID, false)).
|
||||
setPagingDirectory(getPageDir(serverID, false)).
|
||||
setLargeMessagesDirectory(getLargeMessagesDir(serverID, false)).
|
||||
setJournalCompactMinFiles(0).
|
||||
setJournalCompactPercentage(0).
|
||||
setClusterPassword(CLUSTER_PASSWORD);
|
||||
|
||||
configuration.addAddressesSetting("#", new AddressSettings().setAutoCreateJmsQueues(true).setAutoDeleteJmsQueues(true));
|
||||
|
||||
configuration.addAcceptorConfiguration("netty", newURIwithPort(hostAddress, port));
|
||||
configuration.addConnectorConfiguration("netty-connector", newURIwithPort(hostAddress, port));
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
protected Configuration createConfig(final String hostAddress, final int serverID) throws Exception {
|
||||
return createConfig(hostAddress, serverID, Collections.EMPTY_MAP);
|
||||
}
|
||||
|
||||
protected Configuration createConfig(final String hostAddress, final int serverID, Map<String, String> params) throws Exception {
|
||||
ConfigurationImpl configuration = new ConfigurationImpl().setJMXManagementEnabled(false).
|
||||
setSecurityEnabled(false).setJournalMinFiles(2).setJournalFileSize(1000 * 1024).setJournalType(JournalType.NIO).
|
||||
setJournalDirectory(getJournalDir(serverID, false)).
|
||||
setBindingsDirectory(getBindingsDir(serverID, false)).
|
||||
setPagingDirectory(getPageDir(serverID, false)).
|
||||
setLargeMessagesDirectory(getLargeMessagesDir(serverID, false)).
|
||||
setJournalCompactMinFiles(0).
|
||||
setJournalCompactPercentage(0).
|
||||
setClusterPassword(CLUSTER_PASSWORD);
|
||||
|
||||
configuration.addAddressesSetting("#", new AddressSettings().setAutoCreateJmsQueues(true).setAutoDeleteJmsQueues(true));
|
||||
|
||||
configuration.addAcceptorConfiguration("netty", newURI(hostAddress, serverID) + "?" + URISupport.createQueryString(params));
|
||||
configuration.addConnectorConfiguration("netty-connector", newURI(hostAddress, serverID));
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
//extraAcceptor takes form: "?name=value&name1=value ..."
|
||||
protected Configuration createConfig(final int serverID, String extraAcceptorParams) throws Exception {
|
||||
ConfigurationImpl configuration = new ConfigurationImpl().setJMXManagementEnabled(false).
|
||||
setSecurityEnabled(false).setJournalMinFiles(2).setJournalFileSize(100 * 1024).setJournalType(JournalType.NIO).
|
||||
setJournalDirectory(getJournalDir(serverID, false)).
|
||||
setBindingsDirectory(getBindingsDir(serverID, false)).
|
||||
setPagingDirectory(getPageDir(serverID, false)).
|
||||
setLargeMessagesDirectory(getLargeMessagesDir(serverID, false)).
|
||||
setJournalCompactMinFiles(0).
|
||||
setJournalCompactPercentage(0).
|
||||
setClusterPassword(CLUSTER_PASSWORD);
|
||||
|
||||
configuration.addAddressesSetting("#", new AddressSettings().setAutoCreateJmsQueues(true).setAutoDeleteJmsQueues(true));
|
||||
|
||||
String fullAcceptorUri = newURI(serverID) + extraAcceptorParams;
|
||||
configuration.addAcceptorConfiguration("netty", fullAcceptorUri);
|
||||
|
||||
configuration.addConnectorConfiguration("netty-connector", newURI(serverID));
|
||||
return configuration;
|
||||
}
|
||||
|
||||
public void deployClusterConfiguration(Configuration config, Integer ... targetIDs) throws Exception {
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
String separator = "";
|
||||
for (int x : targetIDs) {
|
||||
stringBuffer.append(separator + newURI(x));
|
||||
separator = ",";
|
||||
}
|
||||
|
||||
String ccURI = "static://(" + stringBuffer.toString() + ")?connectorName=netty-connector;retryInterval=500;messageLoadBalancingType=STRICT;maxHops=1";
|
||||
|
||||
config.addClusterConfiguration("clusterCC", ccURI);
|
||||
}
|
||||
|
||||
protected static String newURI(int serverID) {
|
||||
return newURI("localhost", serverID);
|
||||
}
|
||||
|
||||
protected static String newURI(String localhostAddress, int serverID) {
|
||||
return "tcp://" + localhostAddress + ":" + (61616 + serverID);
|
||||
}
|
||||
|
||||
protected static String newURIwithPort(String localhostAddress, int port) throws Exception {
|
||||
return newURIwithPort(localhostAddress, port, Collections.EMPTY_MAP);
|
||||
}
|
||||
|
||||
protected static String newURIwithPort(String localhostAddress, int port, Map<String, String> params) throws Exception {
|
||||
return "tcp://" + localhostAddress + ":" + port + "?" + URISupport.createQueryString(params);
|
||||
}
|
||||
|
||||
public static JMSServerControl createJMSServerControl(final MBeanServer mbeanServer) throws Exception {
|
||||
return (JMSServerControl) createProxy(ObjectNameBuilder.DEFAULT.getJMSServerObjectName(), JMSServerControl.class, mbeanServer);
|
||||
}
|
||||
|
||||
public static JMSQueueControl createJMSQueueControl(final String name,
|
||||
final MBeanServer mbeanServer) throws Exception {
|
||||
return (JMSQueueControl) createProxy(ObjectNameBuilder.DEFAULT.getJMSQueueObjectName(name), JMSQueueControl.class, mbeanServer);
|
||||
}
|
||||
|
||||
private static Object createProxy(final ObjectName objectName,
|
||||
final Class mbeanInterface,
|
||||
final MBeanServer mbeanServer) {
|
||||
return MBeanServerInvocationHandler.newProxyInstance(mbeanServer, objectName, mbeanInterface, false);
|
||||
}
|
||||
|
||||
protected void shutDownClusterServers(EmbeddedJMS[] servers) throws Exception {
|
||||
for (int i = 0; i < servers.length; i++) {
|
||||
try {
|
||||
servers[i].stop();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void shutDownNonClusterServers(EmbeddedJMS[] servers) throws Exception {
|
||||
shutDownClusterServers(servers);
|
||||
}
|
||||
|
||||
protected void setUpNonClusterServers(EmbeddedJMS[] servers) throws Exception {
|
||||
|
||||
Configuration[] serverCfgs = new Configuration[servers.length];
|
||||
for (int i = 0; i < servers.length; i++) {
|
||||
serverCfgs[i] = createConfig(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < servers.length; i++) {
|
||||
servers[i] = new EmbeddedJMS().setConfiguration(serverCfgs[i]).setJmsConfiguration(new JMSConfigurationImpl());
|
||||
}
|
||||
|
||||
for (int i = 0; i < servers.length; i++) {
|
||||
servers[i].start();
|
||||
}
|
||||
}
|
||||
|
||||
protected void setUpClusterServers(EmbeddedJMS[] servers) throws Exception {
|
||||
|
||||
Configuration[] serverCfgs = new Configuration[servers.length];
|
||||
for (int i = 0; i < servers.length; i++) {
|
||||
serverCfgs[i] = createConfig(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < servers.length; i++) {
|
||||
deployClusterConfiguration(serverCfgs[i], getTargets(servers.length, i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < servers.length; i++) {
|
||||
servers[i] = new EmbeddedJMS().setConfiguration(serverCfgs[i]).setJmsConfiguration(new JMSConfigurationImpl());
|
||||
}
|
||||
|
||||
for (int i = 0; i < servers.length; i++) {
|
||||
servers[i].start();
|
||||
}
|
||||
|
||||
for (int i = 0; i < servers.length; i++) {
|
||||
Assert.assertTrue(servers[i].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, servers.length));
|
||||
}
|
||||
}
|
||||
|
||||
private Integer[] getTargets(int total, int self)
|
||||
{
|
||||
int lenTargets = total - self;
|
||||
List<Integer> targets = new ArrayList<>();
|
||||
for (int i = 0; i < lenTargets; i++) {
|
||||
if (i != self) {
|
||||
targets.add(i);
|
||||
}
|
||||
}
|
||||
return targets.toArray(new Integer[0]);
|
||||
}
|
||||
|
||||
public EmbeddedJMS createBroker() throws Exception {
|
||||
Configuration config0 = createConfig(0);
|
||||
EmbeddedJMS newbroker = new EmbeddedJMS().setConfiguration(config0).setJmsConfiguration(new JMSConfigurationImpl());
|
||||
return newbroker;
|
||||
}
|
||||
|
||||
}
|
|
@ -20,6 +20,7 @@ import java.io.IOException;
|
|||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -29,6 +30,8 @@ import javax.net.SocketFactory;
|
|||
import org.apache.activemq.TransportLoggerSupport;
|
||||
import org.apache.activemq.artemiswrapper.ArtemisBrokerHelper;
|
||||
import org.apache.activemq.broker.BrokerRegistry;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.artemiswrapper.ArtemisBrokerWrapper;
|
||||
import org.apache.activemq.openwire.OpenWireFormat;
|
||||
import org.apache.activemq.transport.*;
|
||||
import org.apache.activemq.util.IOExceptionSupport;
|
||||
|
@ -42,31 +45,41 @@ public class TcpTransportFactory extends TransportFactory {
|
|||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TcpTransportFactory.class);
|
||||
|
||||
private static volatile String brokerService = null;
|
||||
|
||||
//if a broker is started or stopped it should set this.
|
||||
public static void setBrokerName(String name) {
|
||||
brokerService = name;
|
||||
}
|
||||
private static volatile InternalServiceInfo brokerService = null;
|
||||
|
||||
@Override
|
||||
public Transport doConnect(URI location) throws Exception {
|
||||
//here check broker, if no broker, we start one
|
||||
Map<String, String> params = URISupport.parseParameters(location);
|
||||
String brokerId = params.remove("invmBrokerId");
|
||||
params.clear();
|
||||
location = URISupport.createRemainingURI(location, params);
|
||||
if (brokerService == null) {
|
||||
boolean autoCreate = true;
|
||||
String create = params.remove("create");
|
||||
if (create != null)
|
||||
{
|
||||
autoCreate = "true".equals(create);
|
||||
}
|
||||
|
||||
ArtemisBrokerHelper.startArtemisBroker(location);
|
||||
brokerService = location.toString();
|
||||
URI location1 = URISupport.createRemainingURI(location, Collections.EMPTY_MAP);
|
||||
|
||||
LOG.info("deciding whether starting an internal broker: " + brokerService + " flag: " + BrokerService.disableWrapper);
|
||||
if (autoCreate && brokerService == null && !BrokerService.disableWrapper && BrokerService.checkPort(location1.getPort())) {
|
||||
|
||||
LOG.info("starting internal broker: " + location1);
|
||||
ArtemisBrokerHelper.startArtemisBroker(location1);
|
||||
brokerService = new InternalServiceInfo(location.toString());
|
||||
|
||||
if (brokerId != null) {
|
||||
BrokerRegistry.getInstance().bind(brokerId, ArtemisBrokerHelper.getBroker());
|
||||
System.out.println("bound: " + brokerId);
|
||||
LOG.info("bound: " + brokerId);
|
||||
}
|
||||
}
|
||||
return super.doConnect(location);
|
||||
//remove unused invm parameters
|
||||
params.remove("broker.persistent");
|
||||
params.remove("broker.useJmx");
|
||||
params.remove("marshal");
|
||||
params.remove("create");
|
||||
URI location2 = URISupport.createRemainingURI(location, params);
|
||||
return super.doConnect(location2);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -173,7 +186,36 @@ public class TcpTransportFactory extends TransportFactory {
|
|||
return new InactivityMonitor(transport, format);
|
||||
}
|
||||
|
||||
//remember call this if the test is using the internal broker.
|
||||
public static void clearService() {
|
||||
brokerService = null;
|
||||
LOG.info("#### clearing internal service " + brokerService);
|
||||
if (brokerService != null) {
|
||||
try {
|
||||
ArtemisBrokerHelper.stopArtemisBroker();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
brokerService = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//added createTime for debugging
|
||||
private static class InternalServiceInfo {
|
||||
private String internalService;
|
||||
private long createTime;
|
||||
|
||||
public InternalServiceInfo(String brokerService) {
|
||||
this.internalService = brokerService;
|
||||
this.createTime = System.currentTimeMillis();
|
||||
LOG.info("just created " + this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return internalService + "@" + createTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,7 @@ public class ActiveMQConnectionFactoryTest extends CombinationTestSupport {
|
|||
connection.close();
|
||||
}
|
||||
|
||||
//we don't support in-vm connector (will we?)
|
||||
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
|
||||
|
@ -124,7 +125,9 @@ public class ActiveMQConnectionFactoryTest extends CombinationTestSupport {
|
|||
connection.close();
|
||||
|
||||
// Verify the broker was destroyed.
|
||||
assertNull(BrokerRegistry.getInstance().lookup("myBroker2"));
|
||||
//I comment out this because this is pure client behavior in
|
||||
//amq5. there shouldn't be any use-case like that with Artemis.
|
||||
//assertNull(BrokerRegistry.getInstance().lookup("myBroker2"));
|
||||
}
|
||||
|
||||
public void testGetBrokerName() throws URISyntaxException, JMSException {
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq;
|
||||
|
||||
import java.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();
|
||||
|
||||
//some internal api we don't implement
|
||||
connectionUri = broker.getDefaultUri();
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
|
@ -126,7 +126,8 @@ public class ActiveMQXAConnectionFactoryTest extends CombinationTestSupport {
|
|||
assertNotNull(BrokerRegistry.getInstance().lookup("myBroker"));
|
||||
connection.close();
|
||||
// Verify the broker was destroyed.
|
||||
assertNull(BrokerRegistry.getInstance().lookup("myBroker"));
|
||||
//comment out this check as it doesn't apply to artemis
|
||||
//assertNull(BrokerRegistry.getInstance().lookup("myBroker"));
|
||||
|
||||
connection.close();
|
||||
}
|
||||
|
@ -383,8 +384,9 @@ public class ActiveMQXAConnectionFactoryTest extends CombinationTestSupport {
|
|||
resource.end(tid, XAResource.TMSUCCESS);
|
||||
resource.commit(tid, true);
|
||||
|
||||
assertTransactionGoneFromBroker(tid);
|
||||
assertTransactionGoneFromConnection(brokerName, xaConnection.getClientID(), xaConnection.getConnectionInfo().getConnectionId(), tid);
|
||||
//not apply to artemis
|
||||
//assertTransactionGoneFromBroker(tid);
|
||||
//assertTransactionGoneFromConnection(brokerName, xaConnection.getClientID(), xaConnection.getConnectionInfo().getConnectionId(), tid);
|
||||
assertSessionGone(xaConnection, session);
|
||||
assertTransactionGoneFromFailoverState(xaConnection, tid);
|
||||
|
||||
|
@ -398,8 +400,8 @@ public class ActiveMQXAConnectionFactoryTest extends CombinationTestSupport {
|
|||
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);
|
||||
//assertTransactionGoneFromBroker(tid);
|
||||
//assertTransactionGoneFromConnection(brokerName, xaConnection.getClientID(), xaConnection.getConnectionInfo().getConnectionId(), tid);
|
||||
assertSessionGone(xaConnection, session);
|
||||
assertTransactionGoneFromFailoverState(xaConnection, tid);
|
||||
|
||||
|
@ -430,7 +432,8 @@ public class ActiveMQXAConnectionFactoryTest extends CombinationTestSupport {
|
|||
|
||||
connection.close();
|
||||
|
||||
assertTransactionGoneFromBroker(tid);
|
||||
//comment out this check as it doesn't apply to artemis
|
||||
//assertTransactionGoneFromBroker(tid);
|
||||
|
||||
broker.stop();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Enforces a test case to run for only an allotted time to prevent them from
|
||||
* hanging and breaking the whole testing.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
public abstract class AutoFailTestSupport extends TestCase {
|
||||
public static final int EXIT_SUCCESS = 0;
|
||||
public static final int EXIT_ERROR = 1;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AutoFailTestSupport.class);
|
||||
|
||||
private long maxTestTime = 5 * 60 * 1000; // 5 mins by default
|
||||
private Thread autoFailThread;
|
||||
|
||||
private boolean verbose = true;
|
||||
private boolean useAutoFail; // Disable auto fail by default
|
||||
private AtomicBoolean isTestSuccess;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
// Runs the auto fail thread before performing any setup
|
||||
if (isAutoFail()) {
|
||||
startAutoFailThread();
|
||||
}
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
// Stops the auto fail thread only after performing any clean up
|
||||
stopAutoFailThread();
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually start the auto fail thread. To start it automatically, just set
|
||||
* the auto fail to true before calling any setup methods. As a rule, this
|
||||
* method is used only when you are not sure, if the setUp and tearDown
|
||||
* method is propagated correctly.
|
||||
*/
|
||||
public void startAutoFailThread() {
|
||||
setAutoFail(true);
|
||||
isTestSuccess = new AtomicBoolean(false);
|
||||
autoFailThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Wait for test to finish succesfully
|
||||
Thread.sleep(getMaxTestTime());
|
||||
} catch (InterruptedException e) {
|
||||
// This usually means the test was successful
|
||||
} finally {
|
||||
// Check if the test was able to tear down succesfully,
|
||||
// which usually means, it has finished its run.
|
||||
if (!isTestSuccess.get()) {
|
||||
LOG.error("Test case has exceeded the maximum allotted time to run of: " + getMaxTestTime() + " ms.");
|
||||
dumpAllThreads(getName());
|
||||
if (System.getProperty("org.apache.activemq.AutoFailTestSupport.disableSystemExit") == null) {
|
||||
System.exit(EXIT_ERROR);
|
||||
} else {
|
||||
LOG.error("No system.exit as it kills surefire - forkedProcessTimeoutInSeconds (surefire.timeout) will kick in eventually see pom.xml surefire plugin config");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, "AutoFailThread");
|
||||
|
||||
if (verbose) {
|
||||
LOG.info("Starting auto fail thread...");
|
||||
}
|
||||
|
||||
LOG.info("Starting auto fail thread...");
|
||||
autoFailThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually stops the auto fail thread. As a rule, this method is used only
|
||||
* when you are not sure, if the setUp and tearDown method is propagated
|
||||
* correctly.
|
||||
*/
|
||||
public void stopAutoFailThread() {
|
||||
if (isAutoFail() && autoFailThread != null && autoFailThread.isAlive()) {
|
||||
isTestSuccess.set(true);
|
||||
|
||||
if (verbose) {
|
||||
LOG.info("Stopping auto fail thread...");
|
||||
}
|
||||
|
||||
LOG.info("Stopping auto fail thread...");
|
||||
autoFailThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the auto fail value. As a rule, this should be used only before any
|
||||
* setup methods is called to automatically enable the auto fail thread in
|
||||
* the setup method of the test case.
|
||||
*
|
||||
* @param val
|
||||
*/
|
||||
public void setAutoFail(boolean val) {
|
||||
this.useAutoFail = val;
|
||||
}
|
||||
|
||||
public boolean isAutoFail() {
|
||||
return this.useAutoFail;
|
||||
}
|
||||
|
||||
/**
|
||||
* The assigned value will only be reflected when the auto fail thread has
|
||||
* started its run. Value is in milliseconds.
|
||||
*
|
||||
* @param val
|
||||
*/
|
||||
public void setMaxTestTime(long val) {
|
||||
this.maxTestTime = val;
|
||||
}
|
||||
|
||||
public long getMaxTestTime() {
|
||||
return this.maxTestTime;
|
||||
}
|
||||
|
||||
|
||||
public static void dumpAllThreads(String prefix) {
|
||||
Map<Thread, StackTraceElement[]> stacks = Thread.getAllStackTraces();
|
||||
for (Entry<Thread, StackTraceElement[]> stackEntry : stacks.entrySet()) {
|
||||
System.err.println(prefix + " " + stackEntry.getKey());
|
||||
for(StackTraceElement element : stackEntry.getValue()) {
|
||||
System.err.println(" " + element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -116,7 +116,7 @@ public abstract class CombinationTestSupport extends AutoFailTestSupport {
|
|||
public static void checkStopped() throws Exception {
|
||||
ArtemisBrokerHelper.stopArtemisBroker();
|
||||
boolean notStopped = BrokerService.checkStopped();
|
||||
TcpTransportFactory.setBrokerName(null);
|
||||
TcpTransportFactory.clearService();
|
||||
if (notStopped) {
|
||||
fail("brokers not stopped see exceptions above");
|
||||
}
|
||||
|
|
|
@ -52,22 +52,50 @@ public class ConnectionCleanupTest extends TestCase {
|
|||
|
||||
try {
|
||||
connection.setClientID("test");
|
||||
// fail("Should have received JMSException");
|
||||
fail("Should have received JMSException");
|
||||
}
|
||||
catch (JMSException e) {
|
||||
}
|
||||
|
||||
connection.cleanup();
|
||||
connection.doCleanup(true);
|
||||
connection.setClientID("test");
|
||||
|
||||
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
try {
|
||||
connection.setClientID("test");
|
||||
// fail("Should have received JMSException");
|
||||
fail("Should have received JMSException");
|
||||
}
|
||||
catch (JMSException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testChangeClientIDDenied() 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();
|
||||
|
||||
try {
|
||||
connection.setClientID("test");
|
||||
fail("Should have received JMSException");
|
||||
} catch (JMSException e) {
|
||||
}
|
||||
|
||||
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
try {
|
||||
connection.setClientID("test");
|
||||
fail("Should have received JMSException");
|
||||
} catch (JMSException e) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,15 +16,23 @@
|
|||
*/
|
||||
package org.apache.activemq;
|
||||
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
|
||||
import org.apache.activemq.artemis.core.server.JournalType;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.JMSConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS;
|
||||
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.junit.rules.TemporaryFolder;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Destination;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* A useful base class which creates and closes an embedded broker
|
||||
|
@ -32,17 +40,27 @@ import javax.jms.Destination;
|
|||
public abstract class EmbeddedBrokerTestSupport extends CombinationTestSupport {
|
||||
|
||||
protected BrokerService broker;
|
||||
// protected String bindAddress = "tcp://localhost:61616";
|
||||
protected String bindAddress = "vm://localhost";
|
||||
protected EmbeddedJMS artemisBroker;
|
||||
protected String bindAddress = "tcp://localhost:61616";
|
||||
protected ConnectionFactory connectionFactory;
|
||||
protected boolean useTopic;
|
||||
protected ActiveMQDestination destination;
|
||||
protected JmsTemplate template;
|
||||
protected boolean disableWrapper = false;
|
||||
|
||||
public TemporaryFolder temporaryFolder;
|
||||
|
||||
public String CLUSTER_PASSWORD = "OPENWIRECLUSTER";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
if (broker == null) {
|
||||
broker = createBroker();
|
||||
BrokerService.disableWrapper = disableWrapper;
|
||||
File tmpRoot = new File("./target/tmp");
|
||||
tmpRoot.mkdirs();
|
||||
temporaryFolder = new TemporaryFolder(tmpRoot);
|
||||
temporaryFolder.create();
|
||||
|
||||
if (artemisBroker == null) {
|
||||
artemisBroker = createArtemisBroker();
|
||||
}
|
||||
startBroker();
|
||||
|
||||
|
@ -58,13 +76,43 @@ public abstract class EmbeddedBrokerTestSupport extends CombinationTestSupport {
|
|||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (broker != null) {
|
||||
if (artemisBroker != null) {
|
||||
try {
|
||||
broker.stop();
|
||||
artemisBroker.stop();
|
||||
artemisBroker = null;
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
temporaryFolder.delete();
|
||||
}
|
||||
|
||||
public String getTmp() {
|
||||
return getTmpFile().getAbsolutePath();
|
||||
}
|
||||
|
||||
public File getTmpFile() {
|
||||
return temporaryFolder.getRoot();
|
||||
}
|
||||
|
||||
protected String getJournalDir(int serverID, boolean backup) {
|
||||
return getTmp() + "/journal_" + serverID + "_" + backup;
|
||||
}
|
||||
|
||||
protected String getBindingsDir(int serverID, boolean backup) {
|
||||
return getTmp() + "/binding_" + serverID + "_" + backup;
|
||||
}
|
||||
|
||||
protected String getPageDir(int serverID, boolean backup) {
|
||||
return getTmp() + "/paging_" + serverID + "_" + backup;
|
||||
}
|
||||
|
||||
protected String getLargeMessagesDir(int serverID, boolean backup) {
|
||||
return getTmp() + "/paging_" + serverID + "_" + backup;
|
||||
}
|
||||
|
||||
protected static String newURI(String localhostAddress, int serverID) {
|
||||
return "tcp://" + localhostAddress + ":" + (61616 + serverID);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,20 +162,44 @@ public abstract class EmbeddedBrokerTestSupport extends CombinationTestSupport {
|
|||
return new ActiveMQConnectionFactory(bindAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create a new broker
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
|
||||
public EmbeddedJMS createArtemisBroker() throws Exception {
|
||||
Configuration config0 = createConfig("localhost", 0);
|
||||
EmbeddedJMS newbroker = new EmbeddedJMS().setConfiguration(config0).setJmsConfiguration(new JMSConfigurationImpl());
|
||||
return newbroker;
|
||||
}
|
||||
|
||||
protected Configuration createConfig(final String hostAddress, final int serverID) throws Exception {
|
||||
ConfigurationImpl configuration = new ConfigurationImpl().setJMXManagementEnabled(false).
|
||||
setSecurityEnabled(false).setJournalMinFiles(2).setJournalFileSize(1000 * 1024).setJournalType(JournalType.NIO).
|
||||
setJournalDirectory(getJournalDir(serverID, false)).
|
||||
setBindingsDirectory(getBindingsDir(serverID, false)).
|
||||
setPagingDirectory(getPageDir(serverID, false)).
|
||||
setLargeMessagesDirectory(getLargeMessagesDir(serverID, false)).
|
||||
setJournalCompactMinFiles(0).
|
||||
setJournalCompactPercentage(0).
|
||||
setClusterPassword(CLUSTER_PASSWORD);
|
||||
|
||||
configuration.addAddressesSetting("#", new AddressSettings().setAutoCreateJmsQueues(true).setAutoDeleteJmsQueues(true));
|
||||
|
||||
configuration.addAcceptorConfiguration("netty", newURI(hostAddress, serverID));
|
||||
configuration.addConnectorConfiguration("netty-connector", newURI(hostAddress, serverID));
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
//we keep this because some other tests uses it.
|
||||
//we'll delete this when those tests are dealt with.
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService answer = new BrokerService();
|
||||
answer.setPersistent(isPersistent());
|
||||
answer.getManagementContext().setCreateConnector(false);
|
||||
answer.addConnector(bindAddress);
|
||||
return answer;
|
||||
}
|
||||
|
||||
protected void startBroker() throws Exception {
|
||||
broker.start();
|
||||
artemisBroker.start();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -98,6 +98,7 @@ public class ExclusiveConsumerStartupDestinationTest extends EmbeddedBrokerTestS
|
|||
}
|
||||
}
|
||||
|
||||
//Exclusive consumer not implemented yet.
|
||||
public void testFailoverToAnotherExclusiveConsumerCreatedFirst() throws JMSException, InterruptedException {
|
||||
Connection conn = createConnection(true);
|
||||
|
||||
|
|
|
@ -26,7 +26,9 @@ import javax.jms.Session;
|
|||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.artemiswrapper.ArtemisBrokerHelper;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.transport.tcp.TcpTransportFactory;
|
||||
|
||||
public class ExclusiveConsumerTest extends TestCase {
|
||||
|
||||
|
@ -43,6 +45,7 @@ public class ExclusiveConsumerTest extends TestCase {
|
|||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
TcpTransportFactory.clearService();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
|
|
|
@ -35,11 +35,18 @@ import javax.jms.MessageProducer;
|
|||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.jms.Topic;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerInvocationHandler;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.broker.jmx.DestinationViewMBean;
|
||||
import org.apache.activemq.artemis.api.core.management.ObjectNameBuilder;
|
||||
import org.apache.activemq.artemis.api.jms.management.DestinationControl;
|
||||
import org.apache.activemq.artemis.api.jms.management.JMSQueueControl;
|
||||
import org.apache.activemq.artemis.api.jms.management.JMSServerControl;
|
||||
import org.apache.activemq.artemis.api.jms.management.TopicControl;
|
||||
import org.apache.activemq.broker.artemiswrapper.ArtemisBrokerWrapper;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -855,7 +862,7 @@ public class JMSConsumerTest extends JmsTestSupport {
|
|||
}
|
||||
|
||||
public void initCombosForTestAckOfExpired() {
|
||||
addCombinationValues("destinationType", new Object[]{Byte.valueOf(ActiveMQDestination.QUEUE_TYPE), Byte.valueOf(ActiveMQDestination.TOPIC_TYPE)});
|
||||
addCombinationValues("destinationType", new Object[]{Byte.valueOf(ActiveMQDestination.QUEUE_TYPE)});
|
||||
}
|
||||
|
||||
public void testAckOfExpired() throws Exception {
|
||||
|
@ -867,6 +874,7 @@ public class JMSConsumerTest extends JmsTestSupport {
|
|||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = (ActiveMQDestination) (destinationType == ActiveMQDestination.QUEUE_TYPE ? session.createQueue("test") : session.createTopic("test"));
|
||||
|
||||
createManagedDestinationOnServer(destination);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
connection.setStatsEnabled(true);
|
||||
|
||||
|
@ -900,25 +908,43 @@ public class JMSConsumerTest extends JmsTestSupport {
|
|||
}
|
||||
assertEquals("consumer has expiredMessages", count, amqConsumer.getConsumerStats().getExpiredMessageCount().getCount());
|
||||
|
||||
DestinationViewMBean view = createView(destination);
|
||||
DestinationControl 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());
|
||||
assertEquals("Wrong inFlightCount: " + view.getDeliveringCount(), 0, view.getDeliveringCount());
|
||||
assertEquals("Wrong dispatch count: " + view.getMessagesAdded(), 8, view.getMessagesAdded());
|
||||
}
|
||||
|
||||
protected DestinationViewMBean createView(ActiveMQDestination destination) throws Exception {
|
||||
private void createManagedDestinationOnServer(ActiveMQDestination destination) throws Exception {
|
||||
String destName = destination.getPhysicalName();
|
||||
ArtemisBrokerWrapper wrapper = (ArtemisBrokerWrapper) broker.getBroker();
|
||||
MBeanServer beanServer = wrapper.getMbeanServer();
|
||||
ObjectName objName = ObjectNameBuilder.DEFAULT.getJMSServerObjectName();
|
||||
JMSServerControl serverControl = MBeanServerInvocationHandler.newProxyInstance(beanServer, objName, JMSServerControl.class, false);
|
||||
serverControl.createQueue(destName);
|
||||
}
|
||||
|
||||
String domain = "org.apache.activemq";
|
||||
ObjectName name;
|
||||
protected DestinationControl createView(ActiveMQDestination destination) throws Exception {
|
||||
|
||||
String destName = destination.getPhysicalName();
|
||||
if (destination.isQueue()) {
|
||||
name = new ObjectName(domain + ":type=Broker,brokerName=localhost,destinationType=Queue,destinationName=test");
|
||||
return createJMSQueueControl(destName);
|
||||
}
|
||||
else {
|
||||
name = new ObjectName(domain + ":type=Broker,brokerName=localhost,destinationType=Topic,destinationName=test");
|
||||
return createJMSTopicControl(destName);
|
||||
}
|
||||
return (DestinationViewMBean) broker.getManagementContext().newProxyInstance(name, DestinationViewMBean.class, true);
|
||||
}
|
||||
|
||||
private JMSQueueControl createJMSQueueControl(String destName) throws Exception {
|
||||
ArtemisBrokerWrapper wrapper = (ArtemisBrokerWrapper) broker.getBroker();
|
||||
MBeanServer beanServer = wrapper.getMbeanServer();
|
||||
ObjectName objName = ObjectNameBuilder.DEFAULT.getJMSQueueObjectName(destName);
|
||||
return MBeanServerInvocationHandler.newProxyInstance(beanServer, objName, JMSQueueControl.class, false);
|
||||
}
|
||||
|
||||
private TopicControl createJMSTopicControl(String destName) throws Exception {
|
||||
ArtemisBrokerWrapper wrapper = (ArtemisBrokerWrapper) broker.getBroker();
|
||||
MBeanServer beanServer = wrapper.getMbeanServer();
|
||||
ObjectName objName = ObjectNameBuilder.DEFAULT.getJMSTopicObjectName(destName);
|
||||
return MBeanServerInvocationHandler.newProxyInstance(beanServer, objName, TopicControl.class, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import javax.jms.DeliveryMode;
|
|||
import org.apache.activemq.test.JmsTopicSendReceiveTest;
|
||||
|
||||
/**
|
||||
*
|
||||
* https://issues.apache.org/jira/browse/ARTEMIS-189
|
||||
*/
|
||||
public class JmsDurableQueueWildcardSendReceiveTest extends JmsTopicSendReceiveTest {
|
||||
|
||||
|
|
|
@ -263,6 +263,7 @@ public class JmsQueueBrowserTest extends JmsTestSupport {
|
|||
consumer.close();
|
||||
}
|
||||
|
||||
//ref: https://issues.apache.org/jira/browse/ARTEMIS-384
|
||||
public void testBrowseReceive() throws Exception {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
ActiveMQQueue destination = new ActiveMQQueue("TEST");
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
/**
|
||||
* 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.Destination;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.apache.activemq.test.JmsResourceProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class JmsQueueTransactionTest extends JmsTransactionTestSupport {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JmsQueueTransactionTest.class);
|
||||
|
||||
/**
|
||||
* @see org.apache.activemq.JmsTransactionTestSupport#getJmsResourceProvider()
|
||||
*/
|
||||
protected JmsResourceProvider getJmsResourceProvider() {
|
||||
JmsResourceProvider p = new JmsResourceProvider();
|
||||
p.setTopic(false);
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the the connection gets reset, the messages will still be
|
||||
* received.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testReceiveTwoThenCloseConnection() throws Exception {
|
||||
Message[] outbound = new Message[] {session.createTextMessage("First Message"), session.createTextMessage("Second Message")};
|
||||
|
||||
// lets consume any outstanding messages from previous test runs
|
||||
beginTx();
|
||||
while (consumer.receive(1000) != null) {
|
||||
}
|
||||
commitTx();
|
||||
|
||||
beginTx();
|
||||
producer.send(outbound[0]);
|
||||
producer.send(outbound[1]);
|
||||
commitTx();
|
||||
|
||||
LOG.info("Sent 0: " + outbound[0]);
|
||||
LOG.info("Sent 1: " + outbound[1]);
|
||||
|
||||
ArrayList<Message> messages = new ArrayList<Message>();
|
||||
beginTx();
|
||||
Message message = consumer.receive(2000);
|
||||
assertEquals(outbound[0], message);
|
||||
|
||||
message = consumer.receive(2000);
|
||||
assertNotNull(message);
|
||||
assertEquals(outbound[1], message);
|
||||
|
||||
// Close and reopen connection.
|
||||
reconnect();
|
||||
|
||||
// Consume again.. the previous message should
|
||||
// get redelivered.
|
||||
beginTx();
|
||||
message = consumer.receive(2000);
|
||||
assertNotNull("Should have re-received the first message again!", message);
|
||||
messages.add(message);
|
||||
assertEquals(outbound[0], message);
|
||||
|
||||
message = consumer.receive(5000);
|
||||
assertNotNull("Should have re-received the second message again!", message);
|
||||
messages.add(message);
|
||||
assertEquals(outbound[1], message);
|
||||
commitTx();
|
||||
|
||||
Message inbound[] = new Message[messages.size()];
|
||||
messages.toArray(inbound);
|
||||
|
||||
assertTextMessagesEqual("Rollback did not work", outbound, inbound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests sending and receiving messages with two sessions(one for producing
|
||||
* and another for consuming).
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSendReceiveInSeperateSessionTest() throws Exception {
|
||||
session.close();
|
||||
int batchCount = 10;
|
||||
|
||||
for (int i = 0; i < batchCount; i++) {
|
||||
// Session that sends messages
|
||||
{
|
||||
Session session = resourceProvider.createSession(connection);
|
||||
this.session = session;
|
||||
MessageProducer producer = resourceProvider.createProducer(session, destination);
|
||||
// consumer = resourceProvider.createConsumer(session,
|
||||
// destination);
|
||||
beginTx();
|
||||
producer.send(session.createTextMessage("Test Message: " + i));
|
||||
commitTx();
|
||||
session.close();
|
||||
}
|
||||
|
||||
// Session that consumes messages
|
||||
{
|
||||
Session session = resourceProvider.createSession(connection);
|
||||
this.session = session;
|
||||
MessageConsumer consumer = resourceProvider.createConsumer(session, destination);
|
||||
|
||||
beginTx();
|
||||
TextMessage message = (TextMessage)consumer.receive(1000 * 5);
|
||||
assertNotNull("Received only " + i + " messages in batch ", message);
|
||||
assertEquals("Test Message: " + i, message.getText());
|
||||
|
||||
commitTx();
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
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
|
||||
beginTx();
|
||||
while (consumer.receive(1000) != null) {
|
||||
}
|
||||
commitTx();
|
||||
|
||||
beginTx();
|
||||
producer.send(outbound[0]);
|
||||
producer.send(outbound[1]);
|
||||
producer.send(outbound[2]);
|
||||
commitTx();
|
||||
|
||||
// Get the first.
|
||||
beginTx();
|
||||
assertEquals(outbound[0], consumer.receive(1000));
|
||||
consumer.close();
|
||||
commitTx();
|
||||
|
||||
beginTx();
|
||||
QueueBrowser browser = session.createBrowser((Queue)destination);
|
||||
Enumeration enumeration = browser.getEnumeration();
|
||||
|
||||
// browse the second
|
||||
assertTrue("should have received the second message", enumeration.hasMoreElements());
|
||||
assertEquals(outbound[1], (Message)enumeration.nextElement());
|
||||
|
||||
// browse the third.
|
||||
assertTrue("Should have received the third message", enumeration.hasMoreElements());
|
||||
assertEquals(outbound[2], (Message)enumeration.nextElement());
|
||||
|
||||
LOG.info("Check for more...");
|
||||
// There should be no more.
|
||||
boolean tooMany = false;
|
||||
while (enumeration.hasMoreElements()) {
|
||||
LOG.info("Got extra message: " + ((TextMessage)enumeration.nextElement()).getText());
|
||||
tooMany = true;
|
||||
}
|
||||
assertFalse(tooMany);
|
||||
LOG.info("close browser...");
|
||||
browser.close();
|
||||
|
||||
LOG.info("reopen and consume...");
|
||||
// Re-open the consumer.
|
||||
consumer = resourceProvider.createConsumer(session, destination);
|
||||
// Receive the second.
|
||||
assertEquals(outbound[1], consumer.receive(1000));
|
||||
// Receive the third.
|
||||
assertEquals(outbound[2], consumer.receive(1000));
|
||||
consumer.close();
|
||||
|
||||
commitTx();
|
||||
}
|
||||
|
||||
public void testCloseConsumer() throws Exception {
|
||||
Destination dest = session.createQueue(getSubject() + "?consumer.prefetchSize=0");
|
||||
producer = session.createProducer(dest);
|
||||
beginTx();
|
||||
producer.send(session.createTextMessage("message 1"));
|
||||
producer.send(session.createTextMessage("message 2"));
|
||||
commitTx();
|
||||
|
||||
beginTx();
|
||||
consumer = session.createConsumer(dest);
|
||||
Message message1 = consumer.receive(1000);
|
||||
String text1 = ((TextMessage)message1).getText();
|
||||
assertNotNull(message1);
|
||||
assertEquals("message 1", text1);
|
||||
|
||||
consumer.close();
|
||||
|
||||
consumer = session.createConsumer(dest);
|
||||
|
||||
Message message2 = consumer.receive(1000);
|
||||
String text2 = ((TextMessage)message2).getText();
|
||||
assertNotNull(message2);
|
||||
assertEquals("message 2", text2);
|
||||
commitTx();
|
||||
}
|
||||
|
||||
}
|
|
@ -29,7 +29,7 @@ import org.apache.activemq.command.ActiveMQDestination;
|
|||
import org.apache.activemq.test.JmsTopicSendReceiveTest;
|
||||
|
||||
/**
|
||||
*
|
||||
* https://issues.apache.org/jira/browse/ARTEMIS-189
|
||||
*/
|
||||
public class JmsQueueWildcardSendReceiveTest extends JmsTopicSendReceiveTest {
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ public class JmsRollbackRedeliveryTest {
|
|||
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination = session.createQueue(destinationName);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
TextMessage msg = (TextMessage) consumer.receive(6000000);
|
||||
TextMessage msg = (TextMessage) consumer.receive(5000);
|
||||
if (msg != null) {
|
||||
if (rolledback.put(msg.getText(), Boolean.TRUE) != null) {
|
||||
LOG.info("Received message " + msg.getText() + " (" + received.getAndIncrement() + ")" + msg.getJMSMessageID());
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
*/
|
||||
package org.apache.activemq;
|
||||
|
||||
import org.apache.activemq.transport.tcp.TcpTransportFactory;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
|
@ -109,5 +111,6 @@ public class JmsTopicSendReceiveWithTwoConnectionsTest extends JmsSendReceiveTes
|
|||
receiveSession.close();
|
||||
sendConnection.close();
|
||||
receiveConnection.close();
|
||||
TcpTransportFactory.clearService();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,722 @@
|
|||
/**
|
||||
* 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.Destination;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.ObjectMessage;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.activemq.broker.BrokerFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.test.JmsResourceProvider;
|
||||
import org.apache.activemq.test.TestSupport;
|
||||
import org.apache.activemq.transport.tcp.TcpTransportFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public abstract class JmsTransactionTestSupport extends TestSupport implements MessageListener {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JmsTransactionTestSupport.class);
|
||||
private static final int MESSAGE_COUNT = 5;
|
||||
private static final String MESSAGE_TEXT = "message";
|
||||
|
||||
protected ConnectionFactory connectionFactory;
|
||||
protected Connection connection;
|
||||
protected Session session;
|
||||
protected MessageConsumer consumer;
|
||||
protected MessageProducer producer;
|
||||
protected JmsResourceProvider resourceProvider;
|
||||
protected Destination destination;
|
||||
protected int batchCount = 10;
|
||||
protected int batchSize = 20;
|
||||
protected BrokerService broker;
|
||||
|
||||
// for message listener test
|
||||
private final List<Message> unackMessages = new ArrayList<Message>(MESSAGE_COUNT);
|
||||
private final List<Message> ackMessages = new ArrayList<Message>(MESSAGE_COUNT);
|
||||
private boolean resendPhase;
|
||||
|
||||
public JmsTransactionTestSupport() {
|
||||
super();
|
||||
}
|
||||
|
||||
public JmsTransactionTestSupport(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see junit.framework.TestCase#setUp()
|
||||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
broker = createBroker();
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
|
||||
resourceProvider = getJmsResourceProvider();
|
||||
topic = resourceProvider.isTopic();
|
||||
// We will be using transacted sessions.
|
||||
setSessionTransacted();
|
||||
connectionFactory = newConnectionFactory();
|
||||
reconnect();
|
||||
}
|
||||
|
||||
protected void setSessionTransacted() {
|
||||
resourceProvider.setTransacted(true);
|
||||
}
|
||||
|
||||
protected ConnectionFactory newConnectionFactory() throws Exception {
|
||||
return resourceProvider.createConnectionFactory();
|
||||
}
|
||||
|
||||
protected void beginTx() throws Exception {
|
||||
//no-op for local tx
|
||||
}
|
||||
|
||||
protected void commitTx() throws Exception {
|
||||
session.commit();
|
||||
}
|
||||
|
||||
protected void rollbackTx() throws Exception {
|
||||
session.rollback();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
protected BrokerService createBroker() throws Exception, URISyntaxException {
|
||||
return BrokerFactory.createBroker(new URI("broker://()/localhost?persistent=false"));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see junit.framework.TestCase#tearDown()
|
||||
*/
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
LOG.info("Closing down connection");
|
||||
|
||||
try {
|
||||
session.close();
|
||||
session = null;
|
||||
connection.close();
|
||||
connection = null;
|
||||
} catch (Exception e) {
|
||||
LOG.info("Caught exception while closing resources.");
|
||||
}
|
||||
|
||||
try {
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
broker = null;
|
||||
} catch (Exception e) {
|
||||
LOG.info("Caught exception while shutting down the Broker", e);
|
||||
}
|
||||
|
||||
LOG.info("Connection closed.");
|
||||
}
|
||||
|
||||
protected abstract JmsResourceProvider getJmsResourceProvider();
|
||||
|
||||
/**
|
||||
* Sends a batch of messages and validates that the messages are received.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSendReceiveTransactedBatches() throws Exception {
|
||||
|
||||
TextMessage message = session.createTextMessage("Batch Message");
|
||||
for (int j = 0; j < batchCount; j++) {
|
||||
LOG.info("Producing bacth " + j + " of " + batchSize + " messages");
|
||||
|
||||
beginTx();
|
||||
for (int i = 0; i < batchSize; i++) {
|
||||
producer.send(message);
|
||||
}
|
||||
messageSent();
|
||||
commitTx();
|
||||
LOG.info("Consuming bacth " + j + " of " + batchSize + " messages");
|
||||
|
||||
beginTx();
|
||||
for (int i = 0; i < batchSize; i++) {
|
||||
message = (TextMessage)consumer.receive(1000 * 5);
|
||||
assertNotNull("Received only " + i + " messages in batch " + j, message);
|
||||
assertEquals("Batch Message", message.getText());
|
||||
}
|
||||
|
||||
commitTx();
|
||||
}
|
||||
}
|
||||
|
||||
protected void messageSent() throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a batch of messages and validates that the rollbacked message was
|
||||
* not consumed.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSendRollback() throws Exception {
|
||||
Message[] outbound = new Message[] {session.createTextMessage("First Message"), session.createTextMessage("Second Message")};
|
||||
|
||||
// sends a message
|
||||
beginTx();
|
||||
producer.send(outbound[0]);
|
||||
commitTx();
|
||||
|
||||
// sends a message that gets rollbacked
|
||||
beginTx();
|
||||
producer.send(session.createTextMessage("I'm going to get rolled back."));
|
||||
rollbackTx();
|
||||
|
||||
// sends a message
|
||||
beginTx();
|
||||
producer.send(outbound[1]);
|
||||
commitTx();
|
||||
|
||||
// receives the first message
|
||||
beginTx();
|
||||
ArrayList<Message> messages = new ArrayList<Message>();
|
||||
LOG.info("About to consume message 1");
|
||||
Message message = consumer.receive(1000);
|
||||
messages.add(message);
|
||||
LOG.info("Received: " + message);
|
||||
|
||||
// receives the second message
|
||||
LOG.info("About to consume message 2");
|
||||
message = consumer.receive(4000);
|
||||
messages.add(message);
|
||||
LOG.info("Received: " + message);
|
||||
|
||||
// validates that the rollbacked was not consumed
|
||||
commitTx();
|
||||
Message inbound[] = new Message[messages.size()];
|
||||
messages.toArray(inbound);
|
||||
assertTextMessagesEqual("Rollback did not work.", outbound, inbound);
|
||||
}
|
||||
|
||||
/**
|
||||
* spec section 3.6 acking a message with automation acks has no effect.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testAckMessageInTx() throws Exception {
|
||||
Message[] outbound = new Message[] {session.createTextMessage("First Message")};
|
||||
|
||||
// sends a message
|
||||
beginTx();
|
||||
producer.send(outbound[0]);
|
||||
outbound[0].acknowledge();
|
||||
commitTx();
|
||||
outbound[0].acknowledge();
|
||||
|
||||
// receives the first message
|
||||
beginTx();
|
||||
ArrayList<Message> messages = new ArrayList<Message>();
|
||||
LOG.info("About to consume message 1");
|
||||
Message message = consumer.receive(1000);
|
||||
messages.add(message);
|
||||
LOG.info("Received: " + message);
|
||||
|
||||
// validates that the rollbacked was not consumed
|
||||
commitTx();
|
||||
Message inbound[] = new Message[messages.size()];
|
||||
messages.toArray(inbound);
|
||||
assertTextMessagesEqual("Message not delivered.", outbound, inbound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a batch of messages and validates that the message sent before
|
||||
* session close is not consumed.
|
||||
*
|
||||
* This test only works with local transactions, not xa.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSendSessionClose() throws Exception {
|
||||
Message[] outbound = new Message[] {session.createTextMessage("First Message"), session.createTextMessage("Second Message")};
|
||||
|
||||
// sends a message
|
||||
beginTx();
|
||||
producer.send(outbound[0]);
|
||||
commitTx();
|
||||
|
||||
// sends a message that gets rollbacked
|
||||
beginTx();
|
||||
producer.send(session.createTextMessage("I'm going to get rolled back."));
|
||||
consumer.close();
|
||||
|
||||
reconnectSession();
|
||||
|
||||
// sends a message
|
||||
producer.send(outbound[1]);
|
||||
commitTx();
|
||||
|
||||
// receives the first message
|
||||
ArrayList<Message> messages = new ArrayList<Message>();
|
||||
LOG.info("About to consume message 1");
|
||||
beginTx();
|
||||
Message message = consumer.receive(1000);
|
||||
messages.add(message);
|
||||
LOG.info("Received: " + message);
|
||||
|
||||
// receives the second message
|
||||
LOG.info("About to consume message 2");
|
||||
message = consumer.receive(4000);
|
||||
messages.add(message);
|
||||
LOG.info("Received: " + message);
|
||||
|
||||
// validates that the rollbacked was not consumed
|
||||
commitTx();
|
||||
Message inbound[] = new Message[messages.size()];
|
||||
messages.toArray(inbound);
|
||||
assertTextMessagesEqual("Rollback did not work.", outbound, inbound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a batch of messages and validates that the message sent before
|
||||
* session close is not consumed.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSendSessionAndConnectionClose() throws Exception {
|
||||
Message[] outbound = new Message[] {session.createTextMessage("First Message"), session.createTextMessage("Second Message")};
|
||||
|
||||
// sends a message
|
||||
beginTx();
|
||||
producer.send(outbound[0]);
|
||||
commitTx();
|
||||
|
||||
// sends a message that gets rollbacked
|
||||
beginTx();
|
||||
producer.send(session.createTextMessage("I'm going to get rolled back."));
|
||||
consumer.close();
|
||||
session.close();
|
||||
|
||||
reconnect();
|
||||
|
||||
// sends a message
|
||||
beginTx();
|
||||
producer.send(outbound[1]);
|
||||
commitTx();
|
||||
|
||||
// receives the first message
|
||||
ArrayList<Message> messages = new ArrayList<Message>();
|
||||
LOG.info("About to consume message 1");
|
||||
beginTx();
|
||||
Message message = consumer.receive(1000);
|
||||
messages.add(message);
|
||||
LOG.info("Received: " + message);
|
||||
|
||||
// receives the second message
|
||||
LOG.info("About to consume message 2");
|
||||
message = consumer.receive(4000);
|
||||
messages.add(message);
|
||||
LOG.info("Received: " + message);
|
||||
|
||||
// validates that the rollbacked was not consumed
|
||||
commitTx();
|
||||
Message inbound[] = new Message[messages.size()];
|
||||
messages.toArray(inbound);
|
||||
assertTextMessagesEqual("Rollback did not work.", outbound, inbound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a batch of messages and validates that the rollbacked message was
|
||||
* redelivered.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testReceiveRollback() throws Exception {
|
||||
Message[] outbound = new Message[] {session.createTextMessage("First Message"), session.createTextMessage("Second Message")};
|
||||
|
||||
// lets consume any outstanding messages from prev test runs
|
||||
beginTx();
|
||||
while (consumer.receive(1000) != null) {
|
||||
}
|
||||
commitTx();
|
||||
|
||||
// sent both messages
|
||||
beginTx();
|
||||
producer.send(outbound[0]);
|
||||
producer.send(outbound[1]);
|
||||
commitTx();
|
||||
|
||||
LOG.info("Sent 0: " + outbound[0]);
|
||||
LOG.info("Sent 1: " + outbound[1]);
|
||||
|
||||
ArrayList<Message> messages = new ArrayList<Message>();
|
||||
beginTx();
|
||||
Message message = consumer.receive(1000);
|
||||
messages.add(message);
|
||||
assertEquals(outbound[0], message);
|
||||
commitTx();
|
||||
|
||||
// rollback so we can get that last message again.
|
||||
beginTx();
|
||||
message = consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
assertEquals(outbound[1], message);
|
||||
rollbackTx();
|
||||
|
||||
// Consume again.. the prev message should
|
||||
// get redelivered.
|
||||
beginTx();
|
||||
message = consumer.receive(5000);
|
||||
assertNotNull("Should have re-received the message again!", message);
|
||||
messages.add(message);
|
||||
commitTx();
|
||||
|
||||
Message inbound[] = new Message[messages.size()];
|
||||
messages.toArray(inbound);
|
||||
assertTextMessagesEqual("Rollback did not work", outbound, inbound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a batch of messages and validates that the rollbacked message was
|
||||
* redelivered.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testReceiveTwoThenRollback() throws Exception {
|
||||
Message[] outbound = new Message[] {session.createTextMessage("First Message"), session.createTextMessage("Second Message")};
|
||||
|
||||
// lets consume any outstanding messages from prev test runs
|
||||
beginTx();
|
||||
while (consumer.receive(1000) != null) {
|
||||
}
|
||||
commitTx();
|
||||
|
||||
//
|
||||
beginTx();
|
||||
producer.send(outbound[0]);
|
||||
producer.send(outbound[1]);
|
||||
commitTx();
|
||||
|
||||
LOG.info("Sent 0: " + outbound[0]);
|
||||
LOG.info("Sent 1: " + outbound[1]);
|
||||
|
||||
ArrayList<Message> messages = new ArrayList<Message>();
|
||||
beginTx();
|
||||
Message message = consumer.receive(1000);
|
||||
assertEquals(outbound[0], message);
|
||||
|
||||
message = consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
assertEquals(outbound[1], message);
|
||||
rollbackTx();
|
||||
|
||||
// Consume again.. the prev message should
|
||||
// get redelivered.
|
||||
beginTx();
|
||||
message = consumer.receive(5000);
|
||||
assertNotNull("Should have re-received the first message again!", message);
|
||||
messages.add(message);
|
||||
assertEquals(outbound[0], message);
|
||||
message = consumer.receive(5000);
|
||||
assertNotNull("Should have re-received the second message again!", message);
|
||||
messages.add(message);
|
||||
assertEquals(outbound[1], message);
|
||||
|
||||
assertNull(consumer.receiveNoWait());
|
||||
commitTx();
|
||||
|
||||
Message inbound[] = new Message[messages.size()];
|
||||
messages.toArray(inbound);
|
||||
assertTextMessagesEqual("Rollback did not work", outbound, inbound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a batch of messages and validates that the rollbacked message was
|
||||
* not consumed.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSendReceiveWithPrefetchOne() throws Exception {
|
||||
setPrefetchToOne();
|
||||
Message[] outbound = new Message[] {session.createTextMessage("First Message"), session.createTextMessage("Second Message"), session.createTextMessage("Third Message"),
|
||||
session.createTextMessage("Fourth Message")};
|
||||
|
||||
beginTx();
|
||||
for (int i = 0; i < outbound.length; i++) {
|
||||
// sends a message
|
||||
producer.send(outbound[i]);
|
||||
}
|
||||
commitTx();
|
||||
|
||||
// receives the first message
|
||||
beginTx();
|
||||
for (int i = 0; i < outbound.length; i++) {
|
||||
LOG.info("About to consume message 1");
|
||||
Message message = consumer.receive(1000);
|
||||
assertNotNull(message);
|
||||
LOG.info("Received: " + message);
|
||||
}
|
||||
|
||||
// validates that the rollbacked was not consumed
|
||||
commitTx();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the test that validates if the rollbacked message was redelivered
|
||||
* multiple times.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testReceiveTwoThenRollbackManyTimes() throws Exception {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
testReceiveTwoThenRollback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a batch of messages and validates that the rollbacked message was
|
||||
* not consumed. This test differs by setting the message prefetch to one.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testSendRollbackWithPrefetchOfOne() throws Exception {
|
||||
setPrefetchToOne();
|
||||
testSendRollback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a batch of messages and and validates that the rollbacked message
|
||||
* was redelivered. This test differs by setting the message prefetch to
|
||||
* one.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testReceiveRollbackWithPrefetchOfOne() throws Exception {
|
||||
setPrefetchToOne();
|
||||
testReceiveRollback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the messages can still be received if the consumer is closed
|
||||
* (session is not closed).
|
||||
*
|
||||
* @throws Exception see http://jira.codehaus.org/browse/AMQ-143
|
||||
*/
|
||||
public void testCloseConsumerBeforeCommit() throws Exception {
|
||||
TextMessage[] outbound = new TextMessage[] {session.createTextMessage("First Message"), session.createTextMessage("Second Message")};
|
||||
|
||||
// lets consume any outstanding messages from prev test runs
|
||||
beginTx();
|
||||
while (consumer.receiveNoWait() != null) {
|
||||
}
|
||||
|
||||
commitTx();
|
||||
|
||||
// sends the messages
|
||||
beginTx();
|
||||
producer.send(outbound[0]);
|
||||
producer.send(outbound[1]);
|
||||
commitTx();
|
||||
LOG.info("Sent 0: " + outbound[0]);
|
||||
LOG.info("Sent 1: " + outbound[1]);
|
||||
|
||||
beginTx();
|
||||
TextMessage message = (TextMessage)consumer.receive(1000);
|
||||
assertEquals(outbound[0].getText(), message.getText());
|
||||
// Close the consumer before the commit. This should not cause the
|
||||
// received message
|
||||
// to rollback.
|
||||
consumer.close();
|
||||
commitTx();
|
||||
|
||||
// Create a new consumer
|
||||
consumer = resourceProvider.createConsumer(session, destination);
|
||||
LOG.info("Created consumer: " + consumer);
|
||||
|
||||
beginTx();
|
||||
message = (TextMessage)consumer.receive(1000);
|
||||
assertEquals(outbound[1].getText(), message.getText());
|
||||
commitTx();
|
||||
}
|
||||
|
||||
public void testChangeMutableObjectInObjectMessageThenRollback() throws Exception {
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
list.add("First");
|
||||
Message outbound = session.createObjectMessage(list);
|
||||
outbound.setStringProperty("foo", "abc");
|
||||
|
||||
beginTx();
|
||||
producer.send(outbound);
|
||||
commitTx();
|
||||
|
||||
LOG.info("About to consume message 1");
|
||||
beginTx();
|
||||
Message message = consumer.receive(5000);
|
||||
|
||||
List<String> body = assertReceivedObjectMessageWithListBody(message);
|
||||
|
||||
// now lets try mutate it
|
||||
try {
|
||||
message.setStringProperty("foo", "def");
|
||||
fail("Cannot change properties of the object!");
|
||||
} catch (JMSException e) {
|
||||
LOG.info("Caught expected exception: " + e, e);
|
||||
}
|
||||
body.clear();
|
||||
body.add("This should never be seen!");
|
||||
rollbackTx();
|
||||
|
||||
beginTx();
|
||||
message = consumer.receive(5000);
|
||||
List<String> secondBody = assertReceivedObjectMessageWithListBody(message);
|
||||
assertNotSame("Second call should return a different body", secondBody, body);
|
||||
commitTx();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<String> assertReceivedObjectMessageWithListBody(Message message) throws JMSException {
|
||||
assertNotNull("Should have received a message!", message);
|
||||
assertEquals("foo header", "abc", message.getStringProperty("foo"));
|
||||
|
||||
assertTrue("Should be an object message but was: " + message, message instanceof ObjectMessage);
|
||||
ObjectMessage objectMessage = (ObjectMessage)message;
|
||||
List<String> body = (List<String>)objectMessage.getObject();
|
||||
LOG.info("Received body: " + body);
|
||||
|
||||
assertEquals("Size of list should be 1", 1, body.size());
|
||||
assertEquals("element 0 of list", "First", body.get(0));
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recreates the connection.
|
||||
*
|
||||
* @throws javax.jms.JMSException
|
||||
*/
|
||||
protected void reconnect() throws Exception {
|
||||
|
||||
if (connection != null) {
|
||||
// Close the prev connection.
|
||||
connection.close();
|
||||
}
|
||||
session = null;
|
||||
connection = resourceProvider.createConnection(connectionFactory);
|
||||
reconnectSession();
|
||||
connection.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recreates the connection.
|
||||
*
|
||||
* @throws javax.jms.JMSException
|
||||
*/
|
||||
protected void reconnectSession() throws JMSException {
|
||||
if (session != null) {
|
||||
session.close();
|
||||
}
|
||||
|
||||
session = resourceProvider.createSession(connection);
|
||||
destination = resourceProvider.createDestination(session, getSubject());
|
||||
producer = resourceProvider.createProducer(session, destination);
|
||||
consumer = resourceProvider.createConsumer(session, destination);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the prefeftch policy to one.
|
||||
*/
|
||||
protected void setPrefetchToOne() {
|
||||
ActiveMQPrefetchPolicy prefetchPolicy = getPrefetchPolicy();
|
||||
prefetchPolicy.setQueuePrefetch(1);
|
||||
prefetchPolicy.setTopicPrefetch(1);
|
||||
prefetchPolicy.setDurableTopicPrefetch(1);
|
||||
prefetchPolicy.setOptimizeDurableTopicPrefetch(1);
|
||||
}
|
||||
|
||||
protected ActiveMQPrefetchPolicy getPrefetchPolicy() {
|
||||
return ((ActiveMQConnection)connection).getPrefetchPolicy();
|
||||
}
|
||||
|
||||
//This test won't work with xa tx so no beginTx() has been added.
|
||||
public void testMessageListener() throws Exception {
|
||||
// send messages
|
||||
for (int i = 0; i < MESSAGE_COUNT; i++) {
|
||||
producer.send(session.createTextMessage(MESSAGE_TEXT + i));
|
||||
}
|
||||
commitTx();
|
||||
consumer.setMessageListener(this);
|
||||
// wait receive
|
||||
waitReceiveUnack();
|
||||
assertEquals(unackMessages.size(), MESSAGE_COUNT);
|
||||
// resend phase
|
||||
waitReceiveAck();
|
||||
assertEquals(ackMessages.size(), MESSAGE_COUNT);
|
||||
// should no longer re-receive
|
||||
consumer.setMessageListener(null);
|
||||
assertNull(consumer.receive(500));
|
||||
reconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
if (!resendPhase) {
|
||||
unackMessages.add(message);
|
||||
if (unackMessages.size() == MESSAGE_COUNT) {
|
||||
try {
|
||||
rollbackTx();
|
||||
resendPhase = true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ackMessages.add(message);
|
||||
if (ackMessages.size() == MESSAGE_COUNT) {
|
||||
try {
|
||||
commitTx();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void waitReceiveUnack() throws Exception {
|
||||
for (int i = 0; i < 100 && !resendPhase; i++) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
assertTrue(resendPhase);
|
||||
}
|
||||
|
||||
private void waitReceiveAck() throws Exception {
|
||||
for (int i = 0; i < 100 && ackMessages.size() < MESSAGE_COUNT; i++) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
assertFalse(ackMessages.size() < MESSAGE_COUNT);
|
||||
}
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -26,8 +26,11 @@ import javax.jms.Session;
|
|||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.artemiswrapper.ArtemisBrokerHelper;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.transport.tcp.TcpTransportFactory;
|
||||
|
||||
//https://issues.apache.org/jira/browse/ARTEMIS-196
|
||||
public class QueueConsumerPriorityTest extends TestCase {
|
||||
|
||||
private static final String VM_BROKER_URL = "vm://localhost?broker.persistent=false&broker.useJmx=true";
|
||||
|
@ -43,6 +46,7 @@ public class QueueConsumerPriorityTest extends TestCase {
|
|||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
TcpTransportFactory.clearService();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
|
|
|
@ -96,12 +96,13 @@ public class ReconnectWithSameClientIDTest extends EmbeddedBrokerTestSupport {
|
|||
|
||||
@Override
|
||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory((useFailover ? "failover:" : "") + broker.getTransportConnectors().get(0).getPublishableConnectString());
|
||||
return new ActiveMQConnectionFactory((useFailover ? "failover:" : "") + newURI("localhost", 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
bindAddress = "tcp://localhost:0";
|
||||
disableWrapper = true;
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ public class RemoveDestinationTest {
|
|||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
BrokerService.disableWrapper = true;
|
||||
broker = BrokerFactory.createBroker(new URI(BROKER_URL));
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
|
@ -62,6 +63,7 @@ public class RemoveDestinationTest {
|
|||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
BrokerService.disableWrapper = false;
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
broker = null;
|
||||
|
|
|
@ -26,6 +26,7 @@ import javax.jms.Session;
|
|||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.artemiswrapper.ArtemisBrokerHelper;
|
||||
import org.apache.activemq.broker.BrokerPlugin;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.TransportConnector;
|
||||
|
@ -34,6 +35,16 @@ import org.apache.activemq.broker.view.ConnectionDotFilePlugin;
|
|||
|
||||
public class TimeStampTest extends TestCase {
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
BrokerService.disableWrapper = true;
|
||||
}
|
||||
@Override
|
||||
public void tearDown() {
|
||||
ArtemisBrokerHelper.stopArtemisBroker();
|
||||
BrokerService.disableWrapper = false;
|
||||
}
|
||||
|
||||
public void test() throws Exception {
|
||||
BrokerService broker = new BrokerService();
|
||||
broker.setPersistent(false);
|
||||
|
@ -91,6 +102,5 @@ public class TimeStampTest extends TestCase {
|
|||
consumer.close();
|
||||
session.close();
|
||||
connection.close();
|
||||
broker.stop();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,14 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
|
||||
import javax.jms.TransactionRolledBackException;
|
||||
|
||||
import org.apache.activemq.artemiswrapper.ArtemisBrokerHelper;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.transaction.Synchronization;
|
||||
import org.apache.activemq.transport.tcp.TcpTransportFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TransactionContextTest {
|
||||
|
@ -36,13 +41,22 @@ public class TransactionContextTest {
|
|||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
connection = factory.createActiveMQConnection();
|
||||
underTest = new TransactionContext(connection);
|
||||
try {
|
||||
connection = factory.createActiveMQConnection();
|
||||
underTest = new TransactionContext(connection);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
connection.close();
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
TcpTransportFactory.clearService();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -104,6 +118,7 @@ public class TransactionContextTest {
|
|||
|
||||
@Test
|
||||
public void testSyncIndexCleared() throws Exception {
|
||||
System.out.println("================================= test testSyncIndexCleared ===========");
|
||||
final AtomicInteger beforeEndCountA = new AtomicInteger(0);
|
||||
final AtomicInteger rollbackCountA = new AtomicInteger(0);
|
||||
Synchronization sync = new Synchronization() {
|
||||
|
|
|
@ -26,10 +26,11 @@ import javax.jms.Queue;
|
|||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.artemis.core.config.Configuration;
|
||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
|
||||
import org.apache.activemq.artemis.jms.server.config.impl.JMSConfigurationImpl;
|
||||
import org.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.region.Subscription;
|
||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ConsumerControl;
|
||||
|
@ -349,8 +350,10 @@ public class ZeroPrefetchConsumerTest extends EmbeddedBrokerTestSupport {
|
|||
assertEquals("broker config prefetch in effect", 0, consumer.info.getCurrentPrefetchSize());
|
||||
|
||||
// verify sub view broker
|
||||
Subscription sub = broker.getRegionBroker().getDestinationMap().get(ActiveMQDestination.transform(brokerZeroQueue)).getConsumers().get(0);
|
||||
assertEquals("broker sub prefetch is correct", 0, sub.getConsumerInfo().getCurrentPrefetchSize());
|
||||
// I comment out this because it checks broker internal
|
||||
// which doesn't apply to artemis broker.
|
||||
//Subscription sub = broker.getRegionBroker().getDestinationMap().get(ActiveMQDestination.transform(brokerZeroQueue)).getConsumers().get(0);
|
||||
//assertEquals("broker sub prefetch is correct", 0, sub.getConsumerInfo().getCurrentPrefetchSize());
|
||||
|
||||
// manipulate Prefetch (like failover and stomp)
|
||||
ConsumerControl consumerControl = new ConsumerControl();
|
||||
|
@ -361,22 +364,22 @@ public class ZeroPrefetchConsumerTest extends EmbeddedBrokerTestSupport {
|
|||
Object reply = ((ActiveMQConnection) connection).getTransport().request(consumerControl);
|
||||
assertTrue("good request", !(reply instanceof ExceptionResponse));
|
||||
assertEquals("broker config prefetch in effect", 0, consumer.info.getCurrentPrefetchSize());
|
||||
assertEquals("broker sub prefetch is correct", 0, sub.getConsumerInfo().getCurrentPrefetchSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService brokerService = super.createBroker();
|
||||
PolicyMap policyMap = new PolicyMap();
|
||||
PolicyEntry zeroPrefetchPolicy = new PolicyEntry();
|
||||
zeroPrefetchPolicy.setQueuePrefetch(0);
|
||||
policyMap.put(ActiveMQDestination.transform(brokerZeroQueue), zeroPrefetchPolicy);
|
||||
brokerService.setDestinationPolicy(policyMap);
|
||||
return brokerService;
|
||||
public EmbeddedJMS createArtemisBroker() throws Exception {
|
||||
Configuration config0 = createConfig("localhost", 0);
|
||||
String coreQueueAddress = "jms.queue." + brokerZeroQueue.getQueueName();
|
||||
AddressSettings addrSettings = new AddressSettings();
|
||||
addrSettings.setQueuePrefetch(0);
|
||||
config0.getAddressesSettings().put(coreQueueAddress, addrSettings);
|
||||
EmbeddedJMS newbroker = new EmbeddedJMS().setConfiguration(config0).setJmsConfiguration(new JMSConfigurationImpl());
|
||||
return newbroker;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
disableWrapper = true;
|
||||
bindAddress = "tcp://localhost:0";
|
||||
super.setUp();
|
||||
|
||||
|
@ -388,11 +391,12 @@ public class ZeroPrefetchConsumerTest extends EmbeddedBrokerTestSupport {
|
|||
@Override
|
||||
protected void startBroker() throws Exception {
|
||||
super.startBroker();
|
||||
bindAddress = broker.getTransportConnectors().get(0).getConnectUri().toString();
|
||||
bindAddress = newURI("localhost", 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
BrokerService.disableWrapper = false;
|
||||
connection.close();
|
||||
super.tearDown();
|
||||
}
|
||||
|
|
|
@ -1,271 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.store.jdbc.JDBCPersistenceAdapter;
|
||||
import org.apache.derby.jdbc.EmbeddedDataSource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Implements the test case attached to:
|
||||
* https://issues.apache.org/jira/browse/AMQ-4351
|
||||
*
|
||||
* This version avoids the spring deps.
|
||||
*/
|
||||
public class AMQ4351Test extends BrokerTestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AMQ4351Test.class);
|
||||
|
||||
public static Test suite() {
|
||||
return suite(AMQ4351Test.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(suite());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService broker = new BrokerService();
|
||||
|
||||
// Lets clean up often.
|
||||
broker.setOfflineDurableSubscriberTaskSchedule(500);
|
||||
broker.setOfflineDurableSubscriberTimeout(2000); // lets delete durable subs much faster.
|
||||
|
||||
JDBCPersistenceAdapter jdbc = new JDBCPersistenceAdapter();
|
||||
EmbeddedDataSource dataSource = new EmbeddedDataSource();
|
||||
dataSource.setDatabaseName("derbyDb");
|
||||
dataSource.setCreateDatabase("create");
|
||||
jdbc.setDataSource(dataSource);
|
||||
|
||||
jdbc.deleteAllMessages();
|
||||
broker.setPersistenceAdapter(jdbc);
|
||||
return broker;
|
||||
}
|
||||
|
||||
ActiveMQConnectionFactory connectionFactory;
|
||||
ActiveMQTopic destination = new ActiveMQTopic("TEST");
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
connectionFactory = new ActiveMQConnectionFactory(broker.getVmConnectorURI());
|
||||
}
|
||||
|
||||
class ProducingClient implements Runnable {
|
||||
|
||||
final AtomicLong size = new AtomicLong();
|
||||
final AtomicBoolean done = new AtomicBoolean();
|
||||
CountDownLatch doneLatch = new CountDownLatch(1);
|
||||
|
||||
Connection connection;
|
||||
Session session;
|
||||
MessageProducer producer;
|
||||
|
||||
ProducingClient() throws JMSException {
|
||||
connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
producer = session.createProducer(destination);
|
||||
}
|
||||
|
||||
private void sendMessage() {
|
||||
try {
|
||||
producer.send(session.createTextMessage("Test"));
|
||||
long i = size.incrementAndGet();
|
||||
if ((i % 1000) == 0) {
|
||||
LOG.info("produced " + i + ".");
|
||||
}
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
new Thread(this, "ProducingClient").start();
|
||||
}
|
||||
|
||||
public void stop() throws InterruptedException {
|
||||
done.set(true);
|
||||
if (!doneLatch.await(20, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
connection.close();
|
||||
doneLatch.await();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
try {
|
||||
while (!done.get()) {
|
||||
sendMessage();
|
||||
Thread.sleep(10);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
done.set(true);
|
||||
}
|
||||
finally {
|
||||
doneLatch.countDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ConsumingClient implements Runnable {
|
||||
|
||||
final String name;
|
||||
final AtomicLong size = new AtomicLong();
|
||||
final AtomicBoolean done = new AtomicBoolean();
|
||||
CountDownLatch doneLatch = new CountDownLatch(1);
|
||||
CountDownLatch started;
|
||||
CountDownLatch finished;
|
||||
|
||||
public ConsumingClient(String name, CountDownLatch started, CountDownLatch finished) {
|
||||
this.name = name;
|
||||
this.started = started;
|
||||
this.finished = finished;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
LOG.info("Starting JMS listener " + name);
|
||||
new Thread(this, "ConsumingClient: " + name).start();
|
||||
}
|
||||
|
||||
public void stopAsync() {
|
||||
finished.countDown();
|
||||
done.set(true);
|
||||
}
|
||||
|
||||
public void stop() throws InterruptedException {
|
||||
stopAsync();
|
||||
doneLatch.await();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
connection.setClientID(name);
|
||||
connection.start();
|
||||
try {
|
||||
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
MessageConsumer consumer = session.createDurableSubscriber(destination, name, null, false);
|
||||
started.countDown();
|
||||
while (!done.get()) {
|
||||
Message msg = consumer.receive(100);
|
||||
if (msg != null) {
|
||||
size.incrementAndGet();
|
||||
session.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
connection.close();
|
||||
LOG.info("Stopped JMS listener " + name);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
done.set(true);
|
||||
}
|
||||
finally {
|
||||
doneLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testAMQ4351() throws InterruptedException, JMSException {
|
||||
LOG.info("Start test.");
|
||||
int subs = 100;
|
||||
CountDownLatch startedLatch = new CountDownLatch(subs - 1);
|
||||
CountDownLatch shutdownLatch = new CountDownLatch(subs - 4);
|
||||
|
||||
ProducingClient producer = new ProducingClient();
|
||||
ConsumingClient listener1 = new ConsumingClient("subscriber-1", startedLatch, shutdownLatch);
|
||||
ConsumingClient listener2 = new ConsumingClient("subscriber-2", startedLatch, shutdownLatch);
|
||||
ConsumingClient listener3 = new ConsumingClient("subscriber-3", startedLatch, shutdownLatch);
|
||||
try {
|
||||
|
||||
listener1.start();
|
||||
listener2.start();
|
||||
listener3.start();
|
||||
|
||||
List<ConsumingClient> subscribers = new ArrayList<>(subs);
|
||||
for (int i = 4; i < subs; i++) {
|
||||
ConsumingClient client = new ConsumingClient("subscriber-" + i, startedLatch, shutdownLatch);
|
||||
subscribers.add(client);
|
||||
client.start();
|
||||
}
|
||||
startedLatch.await(10, TimeUnit.SECONDS);
|
||||
|
||||
LOG.info("All subscribers started.");
|
||||
producer.sendMessage();
|
||||
|
||||
LOG.info("Stopping 97 subscribers....");
|
||||
for (ConsumingClient client : subscribers) {
|
||||
client.stopAsync();
|
||||
}
|
||||
shutdownLatch.await(10, TimeUnit.SECONDS);
|
||||
|
||||
// Start producing messages for 10 minutes, at high rate
|
||||
LOG.info("Starting mass message producer...");
|
||||
producer.start();
|
||||
|
||||
long lastSize = listener1.size.get();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Thread.sleep(1000);
|
||||
long size = listener1.size.get();
|
||||
LOG.info("Listener 1: consumed: " + (size - lastSize));
|
||||
assertTrue(size > lastSize);
|
||||
lastSize = size;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
LOG.info("Stopping clients");
|
||||
listener1.stop();
|
||||
listener2.stop();
|
||||
listener3.stop();
|
||||
producer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -24,6 +24,7 @@ import javax.jms.DeliveryMode;
|
|||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.broker.artemiswrapper.ArtemisBrokerWrapper;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
|
@ -101,6 +102,7 @@ public class BrokerTest extends BrokerTestSupport {
|
|||
addCombinationValues("deliveryMode", new Object[]{Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
||||
}
|
||||
|
||||
//https://issues.apache.org/jira/browse/ARTEMIS-384
|
||||
public void testQueueBrowserWith2Consumers() throws Exception {
|
||||
|
||||
ActiveMQDestination destination = new ActiveMQQueue("TEST");
|
||||
|
@ -454,9 +456,13 @@ public class BrokerTest extends BrokerTestSupport {
|
|||
|
||||
// Commit the transaction.
|
||||
connection1.send(createCommitTransaction1Phase(connectionInfo1, txid));
|
||||
//due to async tx operations, we need some time for message count to go down
|
||||
Thread.sleep(1000);
|
||||
ArtemisBrokerWrapper wrapper = (ArtemisBrokerWrapper) broker.getBroker();
|
||||
long messageCount = wrapper.getAMQueueMessageCount(destination.getPhysicalName());
|
||||
|
||||
// The queue should now only have the remaining 2 messages
|
||||
assertEquals(2, countMessagesInQueue(connection1, connectionInfo1, destination));
|
||||
assertEquals(2, messageCount);
|
||||
}
|
||||
|
||||
public void initCombosForTestConsumerCloseCausesRedelivery() {
|
||||
|
@ -679,6 +685,7 @@ public class BrokerTest extends BrokerTestSupport {
|
|||
addCombinationValues("durableConsumer", new Object[]{Boolean.TRUE, Boolean.FALSE});
|
||||
}
|
||||
|
||||
// https://issues.apache.org/jira/browse/ARTEMIS-402
|
||||
public void testTopicRetroactiveConsumerSeeMessagesBeforeCreation() throws Exception {
|
||||
|
||||
ActiveMQDestination destination = new ActiveMQTopic("TEST");
|
||||
|
@ -1202,6 +1209,7 @@ public class BrokerTest extends BrokerTestSupport {
|
|||
addCombinationValues("deliveryMode", new Object[]{Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
||||
}
|
||||
|
||||
// https://issues.apache.org/jira/browse/ARTEMIS-402
|
||||
public void testTopicNoLocal() throws Exception {
|
||||
|
||||
ActiveMQDestination destination = new ActiveMQTopic("TEST");
|
||||
|
@ -1267,6 +1275,7 @@ public class BrokerTest extends BrokerTestSupport {
|
|||
addCombinationValues("deliveryMode", new Object[]{Integer.valueOf(DeliveryMode.NON_PERSISTENT), Integer.valueOf(DeliveryMode.PERSISTENT)});
|
||||
}
|
||||
|
||||
//https://issues.apache.org/jira/browse/ARTEMIS-402
|
||||
public void testTopicDispatchIsBroadcast() throws Exception {
|
||||
|
||||
ActiveMQDestination destination = new ActiveMQTopic("TEST");
|
||||
|
@ -1463,11 +1472,17 @@ public class BrokerTest extends BrokerTestSupport {
|
|||
assertNotNull(m);
|
||||
assertEquals(m.getMessageId(), message1.getMessageId());
|
||||
|
||||
assertTrue(countMessagesInQueue(connection, connectionInfo, destination) == 2);
|
||||
ArtemisBrokerWrapper wrapper = (ArtemisBrokerWrapper) broker.getBroker();
|
||||
long messageCount = wrapper.getAMQueueMessageCount(destination.getPhysicalName());
|
||||
assertTrue(messageCount == 2);
|
||||
connection.send(createAck(consumerInfo, m, 1, MessageAck.DELIVERED_ACK_TYPE));
|
||||
assertTrue(countMessagesInQueue(connection, connectionInfo, destination) == 2);
|
||||
messageCount = wrapper.getAMQueueMessageCount(destination.getPhysicalName());
|
||||
assertTrue(messageCount == 2);
|
||||
connection.send(createAck(consumerInfo, m, 1, MessageAck.STANDARD_ACK_TYPE));
|
||||
assertTrue(countMessagesInQueue(connection, connectionInfo, destination) == 1);
|
||||
//give some time for broker to count down
|
||||
Thread.sleep(2000);
|
||||
messageCount = wrapper.getAMQueueMessageCount(destination.getPhysicalName());
|
||||
assertTrue(messageCount == 1);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,395 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.jmx;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.store.kahadb.KahaDBStore;
|
||||
import org.apache.activemq.util.Wait;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Used to verify that the BrokerView accessed while the BrokerSerivce is waiting
|
||||
* for a Slow Store startup to complete doesn't throw unexpected NullPointerExceptions.
|
||||
*/
|
||||
public class BrokerViewSlowStoreStartupTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BrokerViewSlowStoreStartupTest.class);
|
||||
|
||||
private final CountDownLatch holdStoreStart = new CountDownLatch(1);
|
||||
private final String brokerName = "brokerViewTest";
|
||||
|
||||
private BrokerService broker;
|
||||
private Thread startThread;
|
||||
|
||||
private BrokerService createBroker() throws Exception {
|
||||
BrokerService broker = new BrokerService();
|
||||
broker.setBrokerName(brokerName);
|
||||
|
||||
KahaDBStore kaha = new KahaDBStore() {
|
||||
|
||||
@Override
|
||||
public void start() throws Exception {
|
||||
LOG.info("Test KahaDB class is waiting for signal to complete its start()");
|
||||
holdStoreStart.await();
|
||||
super.start();
|
||||
LOG.info("Test KahaDB class is completed its start()");
|
||||
}
|
||||
};
|
||||
|
||||
kaha.setDirectory(new File("target/activemq-data/kahadb"));
|
||||
kaha.deleteAllMessages();
|
||||
|
||||
broker.setPersistenceAdapter(kaha);
|
||||
broker.setUseJmx(true);
|
||||
|
||||
return broker;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
broker = createBroker();
|
||||
|
||||
startThread = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
broker.start();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
startThread.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
|
||||
// ensure we don't keep the broker held if an exception occurs somewhere.
|
||||
holdStoreStart.countDown();
|
||||
|
||||
startThread.join();
|
||||
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout = 120000)
|
||||
public void testBrokerViewOnSlowStoreStart() throws Exception {
|
||||
|
||||
// Ensure we have an Admin View.
|
||||
assertTrue(Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return (broker.getAdminView()) != null;
|
||||
}
|
||||
}));
|
||||
|
||||
final BrokerView view = broker.getAdminView();
|
||||
|
||||
try {
|
||||
view.getBrokerName();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getBrokerId();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTotalEnqueueCount();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTotalDequeueCount();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTotalConsumerCount();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTotalProducerCount();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTotalMessageCount();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTotalMessagesCached();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.resetStatistics();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.enableStatistics();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.disableStatistics();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.isStatisticsEnabled();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTopics();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getQueues();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTemporaryTopics();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTemporaryQueues();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTopicSubscribers();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getDurableTopicSubscribers();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getQueueSubscribers();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTemporaryTopicSubscribers();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTemporaryQueueSubscribers();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getInactiveDurableTopicSubscribers();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTopicProducers();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getQueueProducers();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTemporaryTopicProducers();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTemporaryQueueProducers();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.getDynamicDestinationProducers();
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.removeConnector("tcp");
|
||||
fail("Should have thrown a NoSuchElementException");
|
||||
}
|
||||
catch (NoSuchElementException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.removeNetworkConnector("tcp");
|
||||
fail("Should have thrown a NoSuchElementException");
|
||||
}
|
||||
catch (NoSuchElementException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.addTopic("TEST");
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.addQueue("TEST");
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.removeTopic("TEST");
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.removeQueue("TEST");
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.createDurableSubscriber("1", "2", "3", "4");
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
view.destroyDurableSubscriber("1", "2");
|
||||
fail("Should have thrown an IllegalStateException");
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
}
|
||||
|
||||
holdStoreStart.countDown();
|
||||
startThread.join();
|
||||
|
||||
Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return view.getBroker() != null;
|
||||
}
|
||||
});
|
||||
assertNotNull(view.getBroker());
|
||||
|
||||
try {
|
||||
view.getBrokerName();
|
||||
}
|
||||
catch (Exception e) {
|
||||
fail("caught an exception getting the Broker property: " + e.getClass().getName());
|
||||
}
|
||||
|
||||
try {
|
||||
view.getBrokerId();
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
fail("caught an exception getting the Broker property: " + e.getClass().getName());
|
||||
}
|
||||
|
||||
try {
|
||||
view.getTotalEnqueueCount();
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
fail("caught an exception getting the Broker property: " + e.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.jmx;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerInvocationHandler;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class HealthViewMBeanTest extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MBeanTest.class);
|
||||
protected MBeanServer mbeanServer;
|
||||
protected String domain = "org.apache.activemq";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
bindAddress = "tcp://localhost:0";
|
||||
useTopic = false;
|
||||
super.setUp();
|
||||
mbeanServer = broker.getManagementContext().getMBeanServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getPublishableConnectString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService answer = new BrokerService();
|
||||
answer.setPersistent(true);
|
||||
answer.setDeleteAllMessagesOnStartup(true);
|
||||
answer.getSystemUsage().getMemoryUsage().setLimit(1024 * 1024 * 64);
|
||||
answer.getSystemUsage().getTempUsage().setLimit(1024 * 1024 * 64);
|
||||
answer.getSystemUsage().getStoreUsage().setLimit(1024 * 1024 * 64);
|
||||
answer.setUseJmx(true);
|
||||
answer.setSchedulerSupport(true);
|
||||
|
||||
// allow options to be visible via jmx
|
||||
|
||||
answer.addConnector(bindAddress);
|
||||
return answer;
|
||||
}
|
||||
|
||||
public void testHealthView() throws Exception {
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination();
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
|
||||
for (int i = 0; i < 60; i++) {
|
||||
BytesMessage message = session.createBytesMessage();
|
||||
message.writeBytes(new byte[1024 * 1024]);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
Thread.sleep(1000);
|
||||
|
||||
String objectNameStr = broker.getBrokerObjectName().toString();
|
||||
objectNameStr += ",service=Health";
|
||||
ObjectName brokerName = assertRegisteredObjectName(objectNameStr);
|
||||
HealthViewMBean health = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, brokerName, HealthViewMBean.class, true);
|
||||
List<HealthStatus> list = health.healthList();
|
||||
|
||||
for (HealthStatus status : list) {
|
||||
LOG.info("Health status: {}", status);
|
||||
}
|
||||
|
||||
assertEquals(2, list.size());
|
||||
}
|
||||
|
||||
protected ObjectName assertRegisteredObjectName(String name) throws MalformedObjectNameException, NullPointerException {
|
||||
ObjectName objectName = new ObjectName(name);
|
||||
if (mbeanServer.isRegistered(objectName)) {
|
||||
LOG.info("Bean Registered: " + objectName);
|
||||
}
|
||||
else {
|
||||
fail("Could not find MBean!: " + objectName);
|
||||
}
|
||||
return objectName;
|
||||
}
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.jmx;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerInvocationHandler;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.log4j.Level;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Log4JConfigTest extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(Log4JConfigTest.class);
|
||||
|
||||
private static final String BROKER_LOGGER = "org.apache.activemq.broker.BrokerService";
|
||||
|
||||
protected MBeanServer mbeanServer;
|
||||
protected String domain = "org.apache.activemq";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
bindAddress = "tcp://localhost:0";
|
||||
useTopic = false;
|
||||
super.setUp();
|
||||
mbeanServer = broker.getManagementContext().getMBeanServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getPublishableConnectString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService answer = new BrokerService();
|
||||
answer.setPersistent(true);
|
||||
answer.setDeleteAllMessagesOnStartup(true);
|
||||
answer.setUseJmx(true);
|
||||
answer.setSchedulerSupport(true);
|
||||
answer.addConnector(bindAddress);
|
||||
return answer;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLog4JConfigViewExists() throws Exception {
|
||||
String brokerObjectName = broker.getBrokerObjectName().toString();
|
||||
String log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName).toString();
|
||||
assertRegisteredObjectName(log4jConfigViewName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLog4JConfigViewGetLoggers() throws Throwable {
|
||||
String brokerObjectName = broker.getBrokerObjectName().toString();
|
||||
ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName);
|
||||
Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true);
|
||||
|
||||
List<String> loggers = log4jConfigView.getLoggers();
|
||||
assertNotNull(loggers);
|
||||
assertFalse(loggers.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLog4JConfigViewGetLevel() throws Throwable {
|
||||
String brokerObjectName = broker.getBrokerObjectName().toString();
|
||||
ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName);
|
||||
Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true);
|
||||
|
||||
String level = log4jConfigView.getLogLevel(BROKER_LOGGER);
|
||||
assertNotNull(level);
|
||||
assertFalse(level.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLog4JConfigViewGetLevelUnknownLoggerName() throws Throwable {
|
||||
String brokerObjectName = broker.getBrokerObjectName().toString();
|
||||
ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName);
|
||||
Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true);
|
||||
|
||||
// Non-existent loggers will return a name equal to the root level.
|
||||
String level = log4jConfigView.getLogLevel("not.a.logger");
|
||||
assertNotNull(level);
|
||||
assertFalse(level.isEmpty());
|
||||
assertEquals(Logger.getRootLogger().getLevel().toString(), level);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLog4JConfigViewSetLevel() throws Throwable {
|
||||
String brokerObjectName = broker.getBrokerObjectName().toString();
|
||||
ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName);
|
||||
Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true);
|
||||
|
||||
String level = log4jConfigView.getLogLevel(BROKER_LOGGER);
|
||||
assertNotNull(level);
|
||||
assertFalse(level.isEmpty());
|
||||
|
||||
log4jConfigView.setLogLevel(BROKER_LOGGER, "WARN");
|
||||
level = log4jConfigView.getLogLevel(BROKER_LOGGER);
|
||||
assertNotNull(level);
|
||||
assertEquals("WARN", level);
|
||||
|
||||
log4jConfigView.setLogLevel(BROKER_LOGGER, "INFO");
|
||||
level = log4jConfigView.getLogLevel(BROKER_LOGGER);
|
||||
assertNotNull(level);
|
||||
assertEquals("INFO", level);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLog4JConfigViewSetLevelNoChangeIfLevelIsBad() throws Throwable {
|
||||
String brokerObjectName = broker.getBrokerObjectName().toString();
|
||||
ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName);
|
||||
Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true);
|
||||
|
||||
log4jConfigView.setLogLevel(BROKER_LOGGER, "INFO");
|
||||
String level = log4jConfigView.getLogLevel(BROKER_LOGGER);
|
||||
assertNotNull(level);
|
||||
assertEquals("INFO", level);
|
||||
|
||||
log4jConfigView.setLogLevel(BROKER_LOGGER, "BAD");
|
||||
level = log4jConfigView.getLogLevel(BROKER_LOGGER);
|
||||
assertNotNull(level);
|
||||
assertEquals("INFO", level);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLog4JConfigViewGetRootLogLevel() throws Throwable {
|
||||
String brokerObjectName = broker.getBrokerObjectName().toString();
|
||||
ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName);
|
||||
Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true);
|
||||
|
||||
String level = log4jConfigView.getRootLogLevel();
|
||||
assertNotNull(level);
|
||||
assertFalse(level.isEmpty());
|
||||
|
||||
String currentRootLevel = Logger.getRootLogger().getLevel().toString();
|
||||
assertEquals(currentRootLevel, level);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLog4JConfigViewSetRootLevel() throws Throwable {
|
||||
String brokerObjectName = broker.getBrokerObjectName().toString();
|
||||
ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName);
|
||||
Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true);
|
||||
|
||||
String currentRootLevel = Logger.getRootLogger().getLevel().toString();
|
||||
log4jConfigView.setRootLogLevel("WARN");
|
||||
currentRootLevel = Logger.getRootLogger().getLevel().toString();
|
||||
assertEquals("WARN", currentRootLevel);
|
||||
log4jConfigView.setRootLogLevel("INFO");
|
||||
currentRootLevel = Logger.getRootLogger().getLevel().toString();
|
||||
assertEquals("INFO", currentRootLevel);
|
||||
|
||||
Level level;
|
||||
}
|
||||
|
||||
protected ObjectName assertRegisteredObjectName(String name) throws MalformedObjectNameException, NullPointerException {
|
||||
ObjectName objectName = new ObjectName(name);
|
||||
if (mbeanServer.isRegistered(objectName)) {
|
||||
LOG.info("Bean Registered: " + objectName);
|
||||
}
|
||||
else {
|
||||
fail("Could not find MBean!: " + objectName);
|
||||
}
|
||||
return objectName;
|
||||
}
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.jmx;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerInvocationHandler;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class MBeanOperationTimeoutTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MBeanOperationTimeoutTest.class);
|
||||
|
||||
private ActiveMQConnectionFactory connectionFactory;
|
||||
private BrokerService broker;
|
||||
private String connectionUri;
|
||||
private static final String destinationName = "MBeanOperationTimeoutTestQ";
|
||||
private static final String moveToDestinationName = "MBeanOperationTimeoutTestQ.Moved";
|
||||
|
||||
protected MBeanServer mbeanServer;
|
||||
protected String domain = "org.apache.activemq";
|
||||
|
||||
protected int messageCount = 50000;
|
||||
|
||||
@Test(expected = TimeoutException.class)
|
||||
public void testLongOperationTimesOut() throws Exception {
|
||||
|
||||
sendMessages(messageCount);
|
||||
LOG.info("Produced " + messageCount + " messages to the broker.");
|
||||
|
||||
// Now get the QueueViewMBean and purge
|
||||
String objectNameStr = broker.getBrokerObjectName().toString();
|
||||
objectNameStr += ",destinationType=Queue,destinationName=" + destinationName;
|
||||
|
||||
ObjectName queueViewMBeanName = assertRegisteredObjectName(objectNameStr);
|
||||
QueueViewMBean proxy = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, queueViewMBeanName, QueueViewMBean.class, true);
|
||||
|
||||
long count = proxy.getQueueSize();
|
||||
assertEquals("Queue size", count, messageCount);
|
||||
|
||||
LOG.info("Attempting to move one message, TimeoutException expected");
|
||||
proxy.moveMatchingMessagesTo(null, moveToDestinationName);
|
||||
}
|
||||
|
||||
private void sendMessages(int count) throws Exception {
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
try {
|
||||
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
Destination destination = session.createQueue(destinationName);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
for (int i = 0; i < messageCount; i++) {
|
||||
Message message = session.createMessage();
|
||||
message.setIntProperty("id", i);
|
||||
producer.send(message);
|
||||
}
|
||||
session.commit();
|
||||
}
|
||||
finally {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected ObjectName assertRegisteredObjectName(String name) throws MalformedObjectNameException, NullPointerException {
|
||||
ObjectName objectName = new ObjectName(name);
|
||||
if (mbeanServer.isRegistered(objectName)) {
|
||||
LOG.info("Bean Registered: " + objectName);
|
||||
}
|
||||
else {
|
||||
fail("Could not find MBean!: " + objectName);
|
||||
}
|
||||
return objectName;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
broker = createBroker();
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
|
||||
connectionUri = broker.getTransportConnectors().get(0).getPublishableConnectString();
|
||||
connectionFactory = new ActiveMQConnectionFactory(connectionUri);
|
||||
mbeanServer = broker.getManagementContext().getMBeanServer();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
Thread.sleep(500);
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
broker = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService answer = new BrokerService();
|
||||
answer.setMbeanInvocationTimeout(TimeUnit.SECONDS.toMillis(1));
|
||||
answer.setUseJmx(true);
|
||||
answer.addConnector("vm://localhost");
|
||||
answer.setDeleteAllMessagesOnStartup(true);
|
||||
return answer;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,258 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.jmx;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerInvocationHandler;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import junit.textui.TestRunner;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.store.PersistenceAdapter;
|
||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
||||
import org.apache.activemq.store.memory.MemoryPersistenceAdapter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A specific test of Queue.purge() functionality
|
||||
*/
|
||||
public class PurgeTest extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PurgeTest.class);
|
||||
|
||||
protected MBeanServer mbeanServer;
|
||||
protected String domain = "org.apache.activemq";
|
||||
protected String clientID = "foo";
|
||||
|
||||
protected Connection connection;
|
||||
protected boolean transacted;
|
||||
protected int authMode = Session.AUTO_ACKNOWLEDGE;
|
||||
protected int messageCount = 10;
|
||||
public PersistenceAdapter persistenceAdapter;
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestRunner.run(PurgeTest.class);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return suite(PurgeTest.class);
|
||||
}
|
||||
|
||||
public void testPurge() throws Exception {
|
||||
// Send some messages
|
||||
connection = connectionFactory.createConnection();
|
||||
connection.setClientID(clientID);
|
||||
connection.start();
|
||||
Session session = connection.createSession(transacted, authMode);
|
||||
destination = createDestination();
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
for (int i = 0; i < messageCount; i++) {
|
||||
Message message = session.createTextMessage("Message: " + i);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
// Now get the QueueViewMBean and purge
|
||||
String objectNameStr = broker.getBrokerObjectName().toString();
|
||||
objectNameStr += ",destinationType=Queue,destinationName=" + getDestinationString();
|
||||
ObjectName queueViewMBeanName = assertRegisteredObjectName(objectNameStr);
|
||||
QueueViewMBean proxy = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, queueViewMBeanName, QueueViewMBean.class, true);
|
||||
|
||||
long count = proxy.getQueueSize();
|
||||
assertEquals("Queue size", count, messageCount);
|
||||
|
||||
proxy.purge();
|
||||
count = proxy.getQueueSize();
|
||||
assertEquals("Queue size", count, 0);
|
||||
assertEquals("Browse size", proxy.browseMessages().size(), 0);
|
||||
|
||||
// Queues have a special case once there are more than a thousand
|
||||
// dead messages, make sure we hit that.
|
||||
messageCount += 1000;
|
||||
for (int i = 0; i < messageCount; i++) {
|
||||
Message message = session.createTextMessage("Message: " + i);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
count = proxy.getQueueSize();
|
||||
assertEquals("Queue size", count, messageCount);
|
||||
|
||||
proxy.purge();
|
||||
count = proxy.getQueueSize();
|
||||
assertEquals("Queue size", count, 0);
|
||||
assertEquals("Browse size", proxy.browseMessages().size(), 0);
|
||||
|
||||
producer.close();
|
||||
}
|
||||
|
||||
public void initCombosForTestDelete() {
|
||||
addCombinationValues("persistenceAdapter", new Object[]{new MemoryPersistenceAdapter(), new KahaDBPersistenceAdapter()});
|
||||
}
|
||||
|
||||
public void testDeleteSameProducer() throws Exception {
|
||||
connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
destination = createDestination();
|
||||
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
Message message = session.createTextMessage("Test Message");
|
||||
producer.send(message);
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
|
||||
Message received = consumer.receive(1000);
|
||||
assertEquals(message, received);
|
||||
|
||||
ObjectName brokerViewMBeanName = assertRegisteredObjectName(domain + ":type=Broker,brokerName=localhost");
|
||||
BrokerViewMBean brokerProxy = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, brokerViewMBeanName, BrokerViewMBean.class, true);
|
||||
|
||||
brokerProxy.removeQueue(getDestinationString());
|
||||
producer.send(message);
|
||||
|
||||
received = consumer.receive(1000);
|
||||
|
||||
assertNotNull("Message not received", received);
|
||||
assertEquals(message, received);
|
||||
}
|
||||
|
||||
public void testDelete() throws Exception {
|
||||
// Send some messages
|
||||
connection = connectionFactory.createConnection();
|
||||
connection.setClientID(clientID);
|
||||
connection.start();
|
||||
Session session = connection.createSession(transacted, authMode);
|
||||
destination = createDestination();
|
||||
sendMessages(session, messageCount);
|
||||
|
||||
// Now get the QueueViewMBean and purge
|
||||
|
||||
ObjectName queueViewMBeanName = assertRegisteredObjectName(domain + ":type=Broker,brokerName=localhost,destinationType=Queue,destinationName=" + getDestinationString());
|
||||
QueueViewMBean queueProxy = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, queueViewMBeanName, QueueViewMBean.class, true);
|
||||
|
||||
ObjectName brokerViewMBeanName = assertRegisteredObjectName(domain + ":type=Broker,brokerName=localhost");
|
||||
BrokerViewMBean brokerProxy = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, brokerViewMBeanName, BrokerViewMBean.class, true);
|
||||
|
||||
long count = queueProxy.getQueueSize();
|
||||
assertEquals("Queue size", count, messageCount);
|
||||
|
||||
brokerProxy.removeQueue(getDestinationString());
|
||||
|
||||
sendMessages(session, messageCount);
|
||||
|
||||
queueViewMBeanName = assertRegisteredObjectName(domain + ":type=Broker,brokerName=localhost,destinationType=Queue,destinationName=" + getDestinationString());
|
||||
queueProxy = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, queueViewMBeanName, QueueViewMBean.class, true);
|
||||
|
||||
count = queueProxy.getQueueSize();
|
||||
assertEquals("Queue size", count, messageCount);
|
||||
|
||||
queueProxy.purge();
|
||||
|
||||
// Queue have a special case once there are more than a thousand
|
||||
// dead messages, make sure we hit that.
|
||||
messageCount += 1000;
|
||||
sendMessages(session, messageCount);
|
||||
|
||||
count = queueProxy.getQueueSize();
|
||||
assertEquals("Queue size", count, messageCount);
|
||||
|
||||
brokerProxy.removeQueue(getDestinationString());
|
||||
|
||||
sendMessages(session, messageCount);
|
||||
|
||||
queueViewMBeanName = assertRegisteredObjectName(domain + ":type=Broker,brokerName=localhost,destinationType=Queue,destinationName=" + getDestinationString());
|
||||
queueProxy = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, queueViewMBeanName, QueueViewMBean.class, true);
|
||||
|
||||
count = queueProxy.getQueueSize();
|
||||
assertEquals("Queue size", count, messageCount);
|
||||
}
|
||||
|
||||
private void sendMessages(Session session, int count) throws Exception {
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
for (int i = 0; i < messageCount; i++) {
|
||||
Message message = session.createTextMessage("Message: " + i);
|
||||
producer.send(message);
|
||||
}
|
||||
}
|
||||
|
||||
protected ObjectName assertRegisteredObjectName(String name) throws MalformedObjectNameException, NullPointerException {
|
||||
ObjectName objectName = new ObjectName(name);
|
||||
if (mbeanServer.isRegistered(objectName)) {
|
||||
echo("Bean Registered: " + objectName);
|
||||
}
|
||||
else {
|
||||
fail("Could not find MBean!: " + objectName);
|
||||
}
|
||||
return objectName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
bindAddress = "tcp://localhost:0";
|
||||
useTopic = false;
|
||||
super.setUp();
|
||||
mbeanServer = broker.getManagementContext().getMBeanServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService answer = new BrokerService();
|
||||
answer.setUseJmx(true);
|
||||
answer.setEnableStatistics(true);
|
||||
answer.addConnector(bindAddress);
|
||||
answer.setPersistenceAdapter(persistenceAdapter);
|
||||
answer.deleteAllMessages();
|
||||
return answer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getPublishableConnectString());
|
||||
}
|
||||
|
||||
protected void echo(String text) {
|
||||
LOG.info(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the destination used in this test case
|
||||
*/
|
||||
@Override
|
||||
protected String getDestinationString() {
|
||||
return getClass().getName() + "." + getName(true);
|
||||
}
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.jmx;
|
||||
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.net.Socket;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnection;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.network.NetworkConnector;
|
||||
import org.apache.activemq.util.JMXSupport;
|
||||
import org.apache.activemq.util.Wait;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TransportConnectorMBeanTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TransportConnectorMBeanTest.class);
|
||||
|
||||
BrokerService broker;
|
||||
|
||||
@Test
|
||||
public void verifyRemoteAddressInMbeanName() throws Exception {
|
||||
doVerifyRemoteAddressInMbeanName(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyRemoteAddressNotInMbeanName() throws Exception {
|
||||
doVerifyRemoteAddressInMbeanName(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyClientIdNetwork() throws Exception {
|
||||
doVerifyClientIdNetwork(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyClientIdDuplexNetwork() throws Exception {
|
||||
doVerifyClientIdNetwork(true);
|
||||
}
|
||||
|
||||
private void doVerifyClientIdNetwork(boolean duplex) throws Exception {
|
||||
createBroker(true);
|
||||
|
||||
BrokerService networked = new BrokerService();
|
||||
networked.setBrokerName("networked");
|
||||
networked.setPersistent(false);
|
||||
NetworkConnector nc = networked.addNetworkConnector("static:" + broker.getTransportConnectors().get(0).getPublishableConnectString());
|
||||
nc.setDuplex(duplex);
|
||||
networked.start();
|
||||
|
||||
try {
|
||||
assertTrue("presence of mbean with clientId", Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
Set<ObjectName> registeredMbeans = getRegisteredMbeans();
|
||||
return match("_outbound", registeredMbeans);
|
||||
}
|
||||
}));
|
||||
|
||||
}
|
||||
finally {
|
||||
networked.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void doVerifyRemoteAddressInMbeanName(boolean allowRemoteAddress) throws Exception {
|
||||
createBroker(allowRemoteAddress);
|
||||
ActiveMQConnection connection = createConnection();
|
||||
Set<ObjectName> registeredMbeans = getRegisteredMbeans();
|
||||
assertEquals("presence of mbean with clientId", true, match(connection.getClientID(), registeredMbeans));
|
||||
assertEquals("presence of mbean with local port", allowRemoteAddress, match(extractLocalPort(connection), registeredMbeans));
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopBroker() throws Exception {
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean match(String s, Set<ObjectName> registeredMbeans) {
|
||||
String encodedName = JMXSupport.encodeObjectNamePart(s);
|
||||
for (ObjectName name : registeredMbeans) {
|
||||
LOG.info("checking for match:" + encodedName + ", with: " + name.toString());
|
||||
if (name.toString().contains(encodedName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String extractLocalPort(ActiveMQConnection connection) throws Exception {
|
||||
Socket socket = connection.getTransport().narrow(Socket.class);
|
||||
return String.valueOf(socket.getLocalPort());
|
||||
}
|
||||
|
||||
private Set<ObjectName> getRegisteredMbeans() throws Exception {
|
||||
// need a little sleep to ensure JMX is up to date
|
||||
Thread.sleep(200);
|
||||
return broker.getManagementContext().queryNames(null, null);
|
||||
}
|
||||
|
||||
private ActiveMQConnection createConnection() throws Exception {
|
||||
final String opts = "?jms.watchTopicAdvisories=false";
|
||||
ActiveMQConnection connection = (ActiveMQConnection) new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getConnectUri() + opts).createConnection();
|
||||
connection.start();
|
||||
return connection;
|
||||
}
|
||||
|
||||
private void createBroker(boolean allowRemoteAddressInMbeanNames) throws Exception {
|
||||
broker = new BrokerService();
|
||||
broker.setPersistent(false);
|
||||
broker.addConnector("tcp://localhost:0");
|
||||
broker.getManagementContext().setAllowRemoteAddressInMBeanNames(allowRemoteAddressInMbeanNames);
|
||||
broker.start();
|
||||
}
|
||||
|
||||
}
|
|
@ -32,6 +32,7 @@ import junit.framework.TestCase;
|
|||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.ConnectionContext;
|
||||
import org.apache.activemq.broker.ProducerBrokerExchange;
|
||||
import org.apache.activemq.broker.region.SubscriptionStatistics;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTextMessage;
|
||||
|
@ -53,12 +54,13 @@ import org.slf4j.LoggerFactory;
|
|||
/**
|
||||
* @author gtully
|
||||
* @see https://issues.apache.org/activemq/browse/AMQ-2020
|
||||
*/
|
||||
**/
|
||||
public class QueueDuplicatesFromStoreTest extends TestCase {
|
||||
private static final Logger LOG = LoggerFactory
|
||||
.getLogger(QueueDuplicatesFromStoreTest.class);
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(QueueDuplicatesFromStoreTest.class);
|
||||
|
||||
ActiveMQQueue destination = new ActiveMQQueue("queue-" + QueueDuplicatesFromStoreTest.class.getSimpleName());
|
||||
ActiveMQQueue destination = new ActiveMQQueue("queue-"
|
||||
+ QueueDuplicatesFromStoreTest.class.getSimpleName());
|
||||
BrokerService brokerService;
|
||||
|
||||
final static String mesageIdRoot = "11111:22222:";
|
||||
|
@ -89,7 +91,7 @@ public class QueueDuplicatesFromStoreTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testNoDuplicateAfterCacheFullAndAckedWithLargeAuditDepth() throws Exception {
|
||||
doTestNoDuplicateAfterCacheFullAndAcked(1024 * 10);
|
||||
doTestNoDuplicateAfterCacheFullAndAcked(1024*10);
|
||||
}
|
||||
|
||||
public void testNoDuplicateAfterCacheFullAndAckedWithSmallAuditDepth() throws Exception {
|
||||
|
@ -97,13 +99,15 @@ public class QueueDuplicatesFromStoreTest extends TestCase {
|
|||
}
|
||||
|
||||
public void doTestNoDuplicateAfterCacheFullAndAcked(final int auditDepth) throws Exception {
|
||||
final PersistenceAdapter persistenceAdapter = brokerService.getPersistenceAdapter();
|
||||
final MessageStore queueMessageStore = persistenceAdapter.createQueueMessageStore(destination);
|
||||
final PersistenceAdapter persistenceAdapter = brokerService.getPersistenceAdapter();
|
||||
final MessageStore queueMessageStore =
|
||||
persistenceAdapter.createQueueMessageStore(destination);
|
||||
final ConnectionContext contextNotInTx = new ConnectionContext();
|
||||
final ConsumerInfo consumerInfo = new ConsumerInfo();
|
||||
final DestinationStatistics destinationStatistics = new DestinationStatistics();
|
||||
consumerInfo.setExclusive(true);
|
||||
final Queue queue = new Queue(brokerService, destination, queueMessageStore, destinationStatistics, brokerService.getTaskRunnerFactory());
|
||||
final Queue queue = new Queue(brokerService, destination,
|
||||
queueMessageStore, destinationStatistics, brokerService.getTaskRunnerFactory());
|
||||
|
||||
// a workaround for this issue
|
||||
// queue.setUseCache(false);
|
||||
|
@ -134,34 +138,38 @@ public class QueueDuplicatesFromStoreTest extends TestCase {
|
|||
// pull from store in small windows
|
||||
Subscription subscription = new Subscription() {
|
||||
|
||||
private SubscriptionStatistics subscriptionStatistics = new SubscriptionStatistics();
|
||||
|
||||
@Override
|
||||
public void add(MessageReference node) throws Exception {
|
||||
if (enqueueCounter.get() != node.getMessageId().getProducerSequenceId()) {
|
||||
errors.add("Not in sequence at: " + enqueueCounter.get() + ", received: " + node.getMessageId().getProducerSequenceId());
|
||||
errors.add("Not in sequence at: " + enqueueCounter.get() + ", received: "
|
||||
+ node.getMessageId().getProducerSequenceId());
|
||||
}
|
||||
assertEquals("is in order", enqueueCounter.get(), node.getMessageId().getProducerSequenceId());
|
||||
assertEquals("is in order", enqueueCounter.get(), node
|
||||
.getMessageId().getProducerSequenceId());
|
||||
receivedLatch.countDown();
|
||||
enqueueCounter.incrementAndGet();
|
||||
node.decrementReferenceCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(ConnectionContext context, Destination destination) throws Exception {
|
||||
public void add(ConnectionContext context, Destination destination)
|
||||
throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countBeforeFull() {
|
||||
if (isFull()) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return fullWindow - (int) (enqueueCounter.get() - ackedCount.get());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void gc() {
|
||||
|
@ -253,7 +261,8 @@ public class QueueDuplicatesFromStoreTest extends TestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(MessageReference node, MessageEvaluationContext context) throws IOException {
|
||||
public boolean matches(MessageReference node,
|
||||
MessageEvaluationContext context) throws IOException {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -263,11 +272,13 @@ public class QueueDuplicatesFromStoreTest extends TestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void processMessageDispatchNotification(MessageDispatchNotification mdn) throws Exception {
|
||||
public void processMessageDispatchNotification(
|
||||
MessageDispatchNotification mdn) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response pullMessage(ConnectionContext context, MessagePull pull) throws Exception {
|
||||
public Response pullMessage(ConnectionContext context,
|
||||
MessagePull pull) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -277,7 +288,8 @@ public class QueueDuplicatesFromStoreTest extends TestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<MessageReference> remove(ConnectionContext context, Destination destination) throws Exception {
|
||||
public List<MessageReference> remove(ConnectionContext context,
|
||||
Destination destination) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -286,7 +298,9 @@ public class QueueDuplicatesFromStoreTest extends TestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setSelector(String selector) throws InvalidSelectorException, UnsupportedOperationException {
|
||||
public void setSelector(String selector)
|
||||
throws InvalidSelectorException,
|
||||
UnsupportedOperationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -294,7 +308,8 @@ public class QueueDuplicatesFromStoreTest extends TestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean addRecoveredMessage(ConnectionContext context, MessageReference message) throws Exception {
|
||||
public boolean addRecoveredMessage(ConnectionContext context,
|
||||
MessageReference message) throws Exception {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -304,16 +319,18 @@ public class QueueDuplicatesFromStoreTest extends TestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void acknowledge(ConnectionContext context, MessageAck ack) throws Exception {
|
||||
public void acknowledge(ConnectionContext context, MessageAck ack)
|
||||
throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCursorMemoryHighWaterMark() {
|
||||
public int getCursorMemoryHighWaterMark(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCursorMemoryHighWaterMark(int cursorMemoryHighWaterMark) {
|
||||
public void setCursorMemoryHighWaterMark(
|
||||
int cursorMemoryHighWaterMark) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -336,14 +353,24 @@ public class QueueDuplicatesFromStoreTest extends TestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void incrementConsumedCount() {
|
||||
public void incrementConsumedCount(){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetConsumedCount() {
|
||||
public void resetConsumedCount(){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubscriptionStatistics getSubscriptionStatistics() {
|
||||
return subscriptionStatistics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getInFlightMessageSize() {
|
||||
return subscriptionStatistics.getInflightMessageSize().getTotalSize();
|
||||
}
|
||||
};
|
||||
|
||||
queue.addSubscription(contextNotInTx, subscription);
|
||||
|
@ -356,9 +383,12 @@ public class QueueDuplicatesFromStoreTest extends TestCase {
|
|||
for (int j = 0; j < ackBatchSize; j++, removeIndex++) {
|
||||
ackedCount.incrementAndGet();
|
||||
MessageAck ack = new MessageAck();
|
||||
ack.setLastMessageId(new MessageId(mesageIdRoot + removeIndex));
|
||||
ack.setLastMessageId(new MessageId(mesageIdRoot
|
||||
+ removeIndex));
|
||||
ack.setMessageCount(1);
|
||||
queue.removeMessage(contextNotInTx, subscription, new IndirectMessageReference(getMessage(removeIndex)), ack);
|
||||
queue.removeMessage(contextNotInTx, subscription,
|
||||
new IndirectMessageReference(
|
||||
getMessage(removeIndex)), ack);
|
||||
queue.wakeup();
|
||||
|
||||
}
|
||||
|
@ -373,7 +403,8 @@ public class QueueDuplicatesFromStoreTest extends TestCase {
|
|||
|
||||
assertTrue("There are no errors: " + errors, errors.isEmpty());
|
||||
assertEquals(count, enqueueCounter.get());
|
||||
assertEquals("store count is correct", count - removeIndex, queueMessageStore.getMessageCount());
|
||||
assertEquals("store count is correct", count - removeIndex,
|
||||
queueMessageStore.getMessageCount());
|
||||
}
|
||||
|
||||
private Message getMessage(int i) throws Exception {
|
||||
|
|
|
@ -61,7 +61,6 @@ import org.apache.activemq.filter.MessageEvaluationContext;
|
|||
import org.apache.activemq.state.ProducerState;
|
||||
import org.apache.activemq.store.MessageStore;
|
||||
import org.apache.activemq.thread.TaskRunnerFactory;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class SubscriptionAddRemoveQueueTest extends TestCase {
|
||||
|
@ -177,16 +176,20 @@ public class SubscriptionAddRemoveQueueTest extends TestCase {
|
|||
|
||||
public class SimpleImmediateDispatchSubscription implements Subscription, LockOwner {
|
||||
|
||||
List<MessageReference> dispatched = Collections.synchronizedList(new ArrayList<MessageReference>());
|
||||
private SubscriptionStatistics subscriptionStatistics = new SubscriptionStatistics();
|
||||
List<MessageReference> dispatched =
|
||||
Collections.synchronizedList(new ArrayList<MessageReference>());
|
||||
|
||||
|
||||
@Override
|
||||
public void acknowledge(ConnectionContext context, MessageAck ack) throws Exception {
|
||||
public void acknowledge(ConnectionContext context, MessageAck ack)
|
||||
throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(MessageReference node) throws Exception {
|
||||
// immediate dispatch
|
||||
QueueMessageReference qmr = (QueueMessageReference) node;
|
||||
QueueMessageReference qmr = (QueueMessageReference)node;
|
||||
qmr.lock(this);
|
||||
dispatched.add(qmr);
|
||||
}
|
||||
|
@ -400,5 +403,15 @@ public class SubscriptionAddRemoveQueueTest extends TestCase {
|
|||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubscriptionStatistics getSubscriptionStatistics() {
|
||||
return subscriptionStatistics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getInFlightMessageSize() {
|
||||
return subscriptionStatistics.getInflightMessageSize().getTotalSize();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,432 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.region.cursors;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
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.Queue;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.AutoFailTestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.jmx.QueueViewMBean;
|
||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
||||
import org.apache.activemq.broker.region.policy.StorePendingQueueMessageStoragePolicy;
|
||||
import org.apache.activemq.usage.MemoryUsage;
|
||||
import org.apache.activemq.usage.StoreUsage;
|
||||
import org.apache.activemq.usage.SystemUsage;
|
||||
import org.apache.activemq.usage.TempUsage;
|
||||
import org.apache.activemq.util.Wait;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Modified CursorSupport Unit test to reproduce the negative queue issue.
|
||||
*
|
||||
* Keys to reproducing:
|
||||
* 1) Consecutive queues with listener on first sending to second queue
|
||||
* 2) Push each queue to the memory limit
|
||||
* This seems to help reproduce the issue more consistently, but
|
||||
* we have seen times in our production environment where the
|
||||
* negative queue can occur without. Our memory limits are
|
||||
* very high in production and it still happens in varying
|
||||
* frequency.
|
||||
* 3) Prefetch
|
||||
* Lowering the prefetch down to 10 and below seems to help
|
||||
* reduce occurrences.
|
||||
* 4) # of consumers per queue
|
||||
* The issue occurs less with fewer consumers
|
||||
*
|
||||
* Things that do not affect reproduction:
|
||||
* 1) Spring - we use spring in our production applications, but this test case works
|
||||
* with or without it.
|
||||
* 2) transacted
|
||||
*/
|
||||
public class NegativeQueueTest extends AutoFailTestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(NegativeQueueTest.class);
|
||||
|
||||
public static SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd,hh:mm:ss:SSS");
|
||||
|
||||
private static final String QUEUE_1_NAME = "conn.test.queue.1";
|
||||
private static final String QUEUE_2_NAME = "conn.test.queue.2";
|
||||
|
||||
private static final long QUEUE_MEMORY_LIMIT = 2097152;
|
||||
private static final long MEMORY_USAGE = 400000000;
|
||||
private static final long TEMP_USAGE = 200000000;
|
||||
private static final long STORE_USAGE = 1000000000;
|
||||
// ensure we exceed the cache 70%
|
||||
private static final int MESSAGE_COUNT = 2100;
|
||||
|
||||
protected static final boolean TRANSACTED = true;
|
||||
protected static final boolean DEBUG = true;
|
||||
protected static int NUM_CONSUMERS = 20;
|
||||
protected static int PREFETCH_SIZE = 1000;
|
||||
|
||||
protected BrokerService broker;
|
||||
protected String bindAddress = "tcp://localhost:0";
|
||||
|
||||
public void testWithDefaultPrefetch() throws Exception {
|
||||
PREFETCH_SIZE = 1000;
|
||||
NUM_CONSUMERS = 20;
|
||||
blastAndConsume();
|
||||
}
|
||||
|
||||
public void x_testWithDefaultPrefetchFiveConsumers() throws Exception {
|
||||
PREFETCH_SIZE = 1000;
|
||||
NUM_CONSUMERS = 5;
|
||||
blastAndConsume();
|
||||
}
|
||||
|
||||
public void x_testWithDefaultPrefetchTwoConsumers() throws Exception {
|
||||
PREFETCH_SIZE = 1000;
|
||||
NUM_CONSUMERS = 2;
|
||||
blastAndConsume();
|
||||
}
|
||||
|
||||
public void testWithDefaultPrefetchOneConsumer() throws Exception {
|
||||
PREFETCH_SIZE = 1000;
|
||||
NUM_CONSUMERS = 1;
|
||||
blastAndConsume();
|
||||
}
|
||||
|
||||
public void testWithMediumPrefetch() throws Exception {
|
||||
PREFETCH_SIZE = 50;
|
||||
NUM_CONSUMERS = 20;
|
||||
blastAndConsume();
|
||||
}
|
||||
|
||||
public void x_testWithSmallPrefetch() throws Exception {
|
||||
PREFETCH_SIZE = 10;
|
||||
NUM_CONSUMERS = 20;
|
||||
blastAndConsume();
|
||||
}
|
||||
|
||||
public void testWithNoPrefetch() throws Exception {
|
||||
PREFETCH_SIZE = 1;
|
||||
NUM_CONSUMERS = 20;
|
||||
blastAndConsume();
|
||||
}
|
||||
|
||||
public void blastAndConsume() throws Exception {
|
||||
LOG.info(getName());
|
||||
ConnectionFactory factory = createConnectionFactory();
|
||||
|
||||
//get proxy queues for statistics lookups
|
||||
Connection proxyConnection = factory.createConnection();
|
||||
proxyConnection.start();
|
||||
Session proxySession = proxyConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final QueueViewMBean proxyQueue1 = getProxyToQueueViewMBean(proxySession.createQueue(QUEUE_1_NAME));
|
||||
final QueueViewMBean proxyQueue2 = getProxyToQueueViewMBean(proxySession.createQueue(QUEUE_2_NAME));
|
||||
|
||||
// LOAD THE QUEUE
|
||||
Connection producerConnection = factory.createConnection();
|
||||
producerConnection.start();
|
||||
Session session = producerConnection.createSession(TRANSACTED, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination queue = session.createQueue(QUEUE_1_NAME);
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
List<TextMessage> senderList = new ArrayList<>();
|
||||
for (int i = 0; i < MESSAGE_COUNT; i++) {
|
||||
TextMessage msg = session.createTextMessage(i + " " + formatter.format(new Date()));
|
||||
senderList.add(msg);
|
||||
producer.send(msg);
|
||||
if (TRANSACTED)
|
||||
session.commit();
|
||||
if (DEBUG && i % 100 == 0) {
|
||||
int index = (i / 100) + 1;
|
||||
System.out.print(index - ((index / 10) * 10));
|
||||
}
|
||||
}
|
||||
|
||||
//get access to the Queue info
|
||||
if (DEBUG) {
|
||||
System.out.println("");
|
||||
System.out.println("Queue1 Size = " + proxyQueue1.getQueueSize());
|
||||
System.out.println("Queue1 Memory % Used = " + proxyQueue1.getMemoryPercentUsage());
|
||||
System.out.println("Queue1 Memory Available = " + proxyQueue1.getMemoryLimit());
|
||||
}
|
||||
|
||||
// FLUSH THE QUEUE
|
||||
final CountDownLatch latch1 = new CountDownLatch(1);
|
||||
final CountDownLatch latch2 = new CountDownLatch(1);
|
||||
Connection[] consumerConnections1 = new Connection[NUM_CONSUMERS];
|
||||
List<Message> consumerList1 = new ArrayList<>();
|
||||
Connection[] consumerConnections2 = new Connection[NUM_CONSUMERS];
|
||||
Connection[] producerConnections2 = new Connection[NUM_CONSUMERS];
|
||||
List<Message> consumerList2 = new ArrayList<>();
|
||||
|
||||
for (int ix = 0; ix < NUM_CONSUMERS; ix++) {
|
||||
producerConnections2[ix] = factory.createConnection();
|
||||
producerConnections2[ix].start();
|
||||
consumerConnections1[ix] = getConsumerConnection(factory);
|
||||
Session consumerSession = consumerConnections1[ix].createSession(TRANSACTED, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer consumer = consumerSession.createConsumer(session.createQueue(QUEUE_1_NAME));
|
||||
consumer.setMessageListener(new SessionAwareMessageListener(producerConnections2[ix], consumerSession, QUEUE_2_NAME, latch1, consumerList1));
|
||||
}
|
||||
|
||||
latch1.await(200000, TimeUnit.MILLISECONDS);
|
||||
if (DEBUG) {
|
||||
System.out.println("");
|
||||
System.out.println("Queue2 Size = " + proxyQueue2.getQueueSize());
|
||||
System.out.println("Queue2 Memory % Used = " + proxyQueue2.getMemoryPercentUsage());
|
||||
System.out.println("Queue2 Memory Available = " + proxyQueue2.getMemoryLimit());
|
||||
}
|
||||
|
||||
for (int ix = 0; ix < NUM_CONSUMERS; ix++) {
|
||||
consumerConnections2[ix] = getConsumerConnection(factory);
|
||||
Session consumerSession = consumerConnections2[ix].createSession(TRANSACTED, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer consumer = consumerSession.createConsumer(session.createQueue(QUEUE_2_NAME));
|
||||
consumer.setMessageListener(new SessionAwareMessageListener(consumerSession, latch2, consumerList2));
|
||||
}
|
||||
|
||||
boolean success = Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
boolean done = latch2.await(10, TimeUnit.SECONDS);
|
||||
if (DEBUG) {
|
||||
System.out.println("");
|
||||
System.out.println("Queue1 Size = " + proxyQueue1.getQueueSize());
|
||||
System.out.println("Queue1 Memory % Used = " + proxyQueue1.getMemoryPercentUsage());
|
||||
System.out.println("Queue2 Size = " + proxyQueue2.getQueueSize());
|
||||
System.out.println("Queue2 Memory % Used = " + proxyQueue2.getMemoryPercentUsage());
|
||||
System.out.println("Queue2 Memory Available = " + proxyQueue2.getMemoryLimit());
|
||||
}
|
||||
return done;
|
||||
}
|
||||
}, 300 * 1000);
|
||||
if (!success) {
|
||||
dumpAllThreads("blocked waiting on 2");
|
||||
}
|
||||
assertTrue("got all expected messages on 2", success);
|
||||
|
||||
producerConnection.close();
|
||||
for (int ix = 0; ix < NUM_CONSUMERS; ix++) {
|
||||
consumerConnections1[ix].close();
|
||||
consumerConnections2[ix].close();
|
||||
producerConnections2[ix].close();
|
||||
}
|
||||
|
||||
//let the consumer statistics on queue2 have time to update
|
||||
Thread.sleep(500);
|
||||
|
||||
if (DEBUG) {
|
||||
System.out.println("");
|
||||
System.out.println("Queue1 Size = " + proxyQueue1.getQueueSize());
|
||||
System.out.println("Queue1 Memory % Used = " + proxyQueue1.getMemoryPercentUsage());
|
||||
System.out.println("Queue2 Size = " + proxyQueue2.getQueueSize());
|
||||
System.out.println("Queue2 Memory % Used = " + proxyQueue2.getMemoryPercentUsage());
|
||||
}
|
||||
|
||||
Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return 0 == proxyQueue1.getQueueSize();
|
||||
}
|
||||
});
|
||||
assertEquals("Queue1 has gone negative,", 0, proxyQueue1.getQueueSize());
|
||||
|
||||
Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return 0 == proxyQueue2.getQueueSize();
|
||||
}
|
||||
});
|
||||
assertEquals("Queue2 has gone negative,", 0, proxyQueue2.getQueueSize());
|
||||
proxyConnection.close();
|
||||
|
||||
}
|
||||
|
||||
private QueueViewMBean getProxyToQueueViewMBean(Queue queue) throws MalformedObjectNameException, JMSException {
|
||||
final String prefix = "org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Queue,destinationName=";
|
||||
|
||||
ObjectName queueViewMBeanName = new ObjectName(prefix + queue.getQueueName());
|
||||
QueueViewMBean proxy = (QueueViewMBean) broker.getManagementContext().newProxyInstance(queueViewMBeanName, QueueViewMBean.class, true);
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
protected Connection getConsumerConnection(ConnectionFactory fac) throws JMSException {
|
||||
Connection connection = fac.createConnection();
|
||||
connection.start();
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
if (broker == null) {
|
||||
broker = createBroker();
|
||||
}
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
}
|
||||
}
|
||||
|
||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(bindAddress);
|
||||
Properties props = new Properties();
|
||||
props.setProperty("prefetchPolicy.durableTopicPrefetch", "" + PREFETCH_SIZE);
|
||||
props.setProperty("prefetchPolicy.optimizeDurableTopicPrefetch", "" + PREFETCH_SIZE);
|
||||
props.setProperty("prefetchPolicy.queuePrefetch", "" + PREFETCH_SIZE);
|
||||
cf.setProperties(props);
|
||||
return cf;
|
||||
}
|
||||
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService answer = new BrokerService();
|
||||
configureBroker(answer);
|
||||
answer.start();
|
||||
answer.waitUntilStarted();
|
||||
bindAddress = answer.getTransportConnectors().get(0).getConnectUri().toString();
|
||||
return answer;
|
||||
}
|
||||
|
||||
protected void configureBroker(BrokerService answer) throws Exception {
|
||||
PolicyEntry policy = new PolicyEntry();
|
||||
policy.setMemoryLimit(QUEUE_MEMORY_LIMIT);
|
||||
policy.setPendingQueuePolicy(new StorePendingQueueMessageStoragePolicy());
|
||||
|
||||
// disable the cache to be sure setBatch is the problem
|
||||
// will get lots of duplicates
|
||||
// real problem is sync between cursor and store add - leads to out or order messages
|
||||
// in the cursor so setBatch can break.
|
||||
// policy.setUseCache(false);
|
||||
|
||||
PolicyMap pMap = new PolicyMap();
|
||||
pMap.setDefaultEntry(policy);
|
||||
answer.setDestinationPolicy(pMap);
|
||||
answer.setDeleteAllMessagesOnStartup(true);
|
||||
answer.addConnector("tcp://localhost:0");
|
||||
|
||||
MemoryUsage memoryUsage = new MemoryUsage();
|
||||
memoryUsage.setLimit(MEMORY_USAGE);
|
||||
memoryUsage.setPercentUsageMinDelta(20);
|
||||
|
||||
TempUsage tempUsage = new TempUsage();
|
||||
tempUsage.setLimit(TEMP_USAGE);
|
||||
|
||||
StoreUsage storeUsage = new StoreUsage();
|
||||
storeUsage.setLimit(STORE_USAGE);
|
||||
|
||||
SystemUsage systemUsage = new SystemUsage();
|
||||
systemUsage.setMemoryUsage(memoryUsage);
|
||||
systemUsage.setTempUsage(tempUsage);
|
||||
systemUsage.setStoreUsage(storeUsage);
|
||||
answer.setSystemUsage(systemUsage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Message listener that is given the Session for transacted consumers
|
||||
*/
|
||||
class SessionAwareMessageListener implements MessageListener {
|
||||
|
||||
private final List<Message> consumerList;
|
||||
private final CountDownLatch latch;
|
||||
private final Session consumerSession;
|
||||
private Session producerSession;
|
||||
private MessageProducer producer;
|
||||
|
||||
public SessionAwareMessageListener(Session consumerSession, CountDownLatch latch, List<Message> consumerList) {
|
||||
this(null, consumerSession, null, latch, consumerList);
|
||||
}
|
||||
|
||||
public SessionAwareMessageListener(Connection producerConnection,
|
||||
Session consumerSession,
|
||||
String outQueueName,
|
||||
CountDownLatch latch,
|
||||
List<Message> consumerList) {
|
||||
this.consumerList = consumerList;
|
||||
this.latch = latch;
|
||||
this.consumerSession = consumerSession;
|
||||
|
||||
if (producerConnection != null) {
|
||||
try {
|
||||
producerSession = producerConnection.createSession(TRANSACTED, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination queue = producerSession.createQueue(outQueueName);
|
||||
producer = producerSession.createProducer(queue);
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(Message msg) {
|
||||
try {
|
||||
if (producer == null) {
|
||||
// sleep to act as a slow consumer
|
||||
// which will force a mix of direct and polled dispatching
|
||||
// using the cursor on the broker
|
||||
Thread.sleep(50);
|
||||
}
|
||||
else {
|
||||
producer.send(msg);
|
||||
if (TRANSACTED)
|
||||
producerSession.commit();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
synchronized (consumerList) {
|
||||
consumerList.add(msg);
|
||||
if (DEBUG && consumerList.size() % 100 == 0) {
|
||||
int index = consumerList.size() / 100;
|
||||
System.out.print(index - ((index / 10) * 10));
|
||||
}
|
||||
if (consumerList.size() == MESSAGE_COUNT) {
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
if (TRANSACTED) {
|
||||
try {
|
||||
consumerSession.commit();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.spring.ConsumerBean;
|
||||
import org.apache.activemq.xbean.XBeanBrokerFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class CompositeQueueTest extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CompositeQueueTest.class);
|
||||
|
||||
protected int total = 10;
|
||||
protected Connection connection;
|
||||
public String messageSelector1, messageSelector2 = null;
|
||||
|
||||
public void testVirtualTopicCreation() throws Exception {
|
||||
if (connection == null) {
|
||||
connection = createConnection();
|
||||
}
|
||||
connection.start();
|
||||
|
||||
ConsumerBean messageList1 = new ConsumerBean();
|
||||
ConsumerBean messageList2 = new ConsumerBean();
|
||||
messageList1.setVerbose(true);
|
||||
messageList2.setVerbose(true);
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
Destination producerDestination = getProducerDestination();
|
||||
Destination destination1 = getConsumer1Dsetination();
|
||||
Destination destination2 = getConsumer2Dsetination();
|
||||
|
||||
LOG.info("Sending to: " + producerDestination);
|
||||
LOG.info("Consuming from: " + destination1 + " and " + destination2);
|
||||
|
||||
MessageConsumer c1 = session.createConsumer(destination1, messageSelector1);
|
||||
MessageConsumer c2 = session.createConsumer(destination2, messageSelector2);
|
||||
|
||||
c1.setMessageListener(messageList1);
|
||||
c2.setMessageListener(messageList2);
|
||||
|
||||
// create topic producer
|
||||
MessageProducer producer = session.createProducer(producerDestination);
|
||||
assertNotNull(producer);
|
||||
|
||||
for (int i = 0; i < total; i++) {
|
||||
producer.send(createMessage(session, i));
|
||||
}
|
||||
|
||||
assertMessagesArrived(messageList1, messageList2);
|
||||
}
|
||||
|
||||
protected void assertMessagesArrived(ConsumerBean messageList1, ConsumerBean messageList2) {
|
||||
messageList1.assertMessagesArrived(total);
|
||||
messageList2.assertMessagesArrived(total);
|
||||
}
|
||||
|
||||
protected TextMessage createMessage(Session session, int i) throws JMSException {
|
||||
TextMessage textMessage = session.createTextMessage("message: " + i);
|
||||
if (i % 2 != 0) {
|
||||
textMessage.setStringProperty("odd", "yes");
|
||||
}
|
||||
else {
|
||||
textMessage.setStringProperty("odd", "no");
|
||||
}
|
||||
textMessage.setIntProperty("i", i);
|
||||
return textMessage;
|
||||
}
|
||||
|
||||
protected Destination getConsumer1Dsetination() {
|
||||
return new ActiveMQQueue("FOO");
|
||||
}
|
||||
|
||||
protected Destination getConsumer2Dsetination() {
|
||||
return new ActiveMQTopic("BAR");
|
||||
}
|
||||
|
||||
protected Destination getProducerDestination() {
|
||||
return new ActiveMQQueue("MY.QUEUE");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
XBeanBrokerFactory factory = new XBeanBrokerFactory();
|
||||
BrokerService answer = factory.createBroker(new URI(getBrokerConfigUri()));
|
||||
return answer;
|
||||
}
|
||||
|
||||
protected String getBrokerConfigUri() {
|
||||
return "org/apache/activemq/broker/virtual/composite-queue.xml";
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import javax.jms.Destination;
|
||||
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class CompositeTopicTest extends CompositeQueueTest {
|
||||
|
||||
@Override
|
||||
protected Destination getConsumer1Dsetination() {
|
||||
return new ActiveMQQueue("FOO");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Destination getConsumer2Dsetination() {
|
||||
return new ActiveMQTopic("BAR");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Destination getProducerDestination() {
|
||||
return new ActiveMQTopic("MY.TOPIC");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBrokerConfigUri() {
|
||||
return "org/apache/activemq/broker/virtual/composite-topic.xml";
|
||||
}
|
||||
}
|
|
@ -1,283 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.Topic;
|
||||
import javax.jms.TopicSubscriber;
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanServerConnection;
|
||||
import javax.management.ObjectInstance;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.remote.JMXConnector;
|
||||
import javax.management.remote.JMXConnectorFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
|
||||
import org.apache.activemq.broker.Broker;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.ConnectionContext;
|
||||
import org.apache.activemq.broker.ProducerBrokerExchange;
|
||||
import org.apache.activemq.broker.region.Destination;
|
||||
import org.apache.activemq.broker.region.DestinationFilter;
|
||||
import org.apache.activemq.broker.region.DestinationInterceptor;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.Message;
|
||||
import org.apache.activemq.xbean.XBeanBrokerFactory;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Test for AMQ-4571.
|
||||
* checks that durable subscription is fully unregistered
|
||||
* when using nested destination interceptors.
|
||||
*/
|
||||
public class DestinationInterceptorDurableSubTest extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private static final transient Logger LOG = LoggerFactory.getLogger(DestinationInterceptorDurableSubTest.class);
|
||||
private MBeanServerConnection mbsc = null;
|
||||
public static final String JMX_CONTEXT_BASE_NAME = "org.apache.activemq:type=Broker,brokerName=localhost,destinationType=Topic,destinationName=";
|
||||
|
||||
/**
|
||||
* Tests AMQ-4571.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testVirtualTopicRemoval() throws Exception {
|
||||
|
||||
LOG.debug("Running testVirtualTopicRemoval()");
|
||||
String clientId1 = "myId1";
|
||||
String clientId2 = "myId2";
|
||||
|
||||
Connection conn = null;
|
||||
Session session = null;
|
||||
|
||||
try {
|
||||
assertTrue(broker.isStarted());
|
||||
|
||||
// create durable sub 1
|
||||
conn = createConnection();
|
||||
conn.setClientID(clientId1);
|
||||
conn.start();
|
||||
session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
// Topic topic = session.createTopic(destination.getPhysicalName());
|
||||
TopicSubscriber sub1 = session.createDurableSubscriber((Topic) destination, clientId1);
|
||||
|
||||
// create durable sub 2
|
||||
TopicSubscriber sub2 = session.createDurableSubscriber((Topic) destination, clientId2);
|
||||
|
||||
// verify two subs registered in JMX
|
||||
assertSubscriptionCount(destination.getPhysicalName(), 2);
|
||||
assertTrue(isSubRegisteredInJmx(destination.getPhysicalName(), clientId1));
|
||||
assertTrue(isSubRegisteredInJmx(destination.getPhysicalName(), clientId2));
|
||||
|
||||
// delete sub 1
|
||||
sub1.close();
|
||||
session.unsubscribe(clientId1);
|
||||
|
||||
// verify only one sub registered in JMX
|
||||
assertSubscriptionCount(destination.getPhysicalName(), 1);
|
||||
assertFalse(isSubRegisteredInJmx(destination.getPhysicalName(), clientId1));
|
||||
assertTrue(isSubRegisteredInJmx(destination.getPhysicalName(), clientId2));
|
||||
|
||||
// delete sub 2
|
||||
sub2.close();
|
||||
session.unsubscribe(clientId2);
|
||||
|
||||
// verify no sub registered in JMX
|
||||
assertSubscriptionCount(destination.getPhysicalName(), 0);
|
||||
assertFalse(isSubRegisteredInJmx(destination.getPhysicalName(), clientId1));
|
||||
assertFalse(isSubRegisteredInJmx(destination.getPhysicalName(), clientId2));
|
||||
}
|
||||
finally {
|
||||
session.close();
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to broker using JMX
|
||||
*
|
||||
* @return The JMX connection
|
||||
* @throws IOException in case of any errors
|
||||
*/
|
||||
protected MBeanServerConnection connectJMXBroker() throws IOException {
|
||||
// connect to broker via JMX
|
||||
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:1299/jmxrmi");
|
||||
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
|
||||
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
|
||||
LOG.debug("JMX connection established");
|
||||
return mbsc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the Subscriptions JMX attribute of a topic has the expected
|
||||
* count.
|
||||
*
|
||||
* @param topicName name of the topic destination
|
||||
* @param expectedCount expected number of subscriptions
|
||||
* @return
|
||||
*/
|
||||
protected boolean assertSubscriptionCount(String topicName, int expectedCount) {
|
||||
try {
|
||||
if (mbsc == null) {
|
||||
mbsc = connectJMXBroker();
|
||||
}
|
||||
// query broker queue size
|
||||
ObjectName[] tmp = (ObjectName[]) mbsc.getAttribute(new ObjectName(JMX_CONTEXT_BASE_NAME + topicName), "Subscriptions");
|
||||
assertEquals(expectedCount, tmp.length);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LOG.error(ex.getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a subscriptions for topic topicName with subName is registered in JMX
|
||||
*
|
||||
* @param topicName physical name of topic destination (excluding prefix 'topic://')
|
||||
* @param subName name of the durable subscription
|
||||
* @return true if registered, false otherwise
|
||||
*/
|
||||
protected boolean isSubRegisteredInJmx(String topicName, String subName) {
|
||||
|
||||
try {
|
||||
if (mbsc == null) {
|
||||
mbsc = connectJMXBroker();
|
||||
}
|
||||
|
||||
// A durable sub is registered under the Subscriptions JMX attribute of the topic and
|
||||
// as its own ObjectInstance under the topic's Consumer namespace.
|
||||
// AMQ-4571 only removed the latter not the former on unsubscribe(), so we need
|
||||
// to check against both.
|
||||
ObjectName[] names = (ObjectName[]) mbsc.getAttribute(new ObjectName(JMX_CONTEXT_BASE_NAME + topicName), "Subscriptions");
|
||||
ObjectInstance instance = mbsc.getObjectInstance(new ObjectName(JMX_CONTEXT_BASE_NAME +
|
||||
topicName +
|
||||
",endpoint=Consumer,clientId=myId1,consumerId=Durable(myId1_" +
|
||||
subName +
|
||||
")"));
|
||||
|
||||
if (instance == null)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (names[i].toString().contains(subName))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (InstanceNotFoundException ine) {
|
||||
//this may be expected so log at info level
|
||||
LOG.info(ine.toString());
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LOG.error(ex.toString());
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
XBeanBrokerFactory factory = new XBeanBrokerFactory();
|
||||
BrokerService answer = factory.createBroker(new URI(getBrokerConfigUri()));
|
||||
|
||||
// lets disable persistence as we are a test
|
||||
answer.setPersistent(false);
|
||||
useTopic = true;
|
||||
return answer;
|
||||
}
|
||||
|
||||
protected String getBrokerConfigUri() {
|
||||
return "org/apache/activemq/broker/virtual/virtual-topics-and-interceptor.xml";
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple but custom topic interceptor.
|
||||
* To be used for testing nested interceptors in conjunction with
|
||||
* virtual topic interceptor.
|
||||
*/
|
||||
public static class SimpleDestinationInterceptor implements DestinationInterceptor {
|
||||
|
||||
private final Logger LOG = LoggerFactory.getLogger(SimpleDestinationInterceptor.class);
|
||||
private BrokerService broker;
|
||||
|
||||
public SimpleDestinationInterceptor() {
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.activemq.broker.BrokerServiceAware#setBrokerService(org.apache.activemq.broker.BrokerService)
|
||||
*/
|
||||
public void setBrokerService(BrokerService brokerService) {
|
||||
LOG.info("setBrokerService()");
|
||||
this.broker = brokerService;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.activemq.broker.region.DestinationInterceptor#intercept(org.apache.activemq.broker.region.Destination)
|
||||
*/
|
||||
@Override
|
||||
public Destination intercept(final Destination destination) {
|
||||
LOG.info("intercept({})", destination.getName());
|
||||
|
||||
if (!destination.getActiveMQDestination().getPhysicalName().startsWith("ActiveMQ")) {
|
||||
return new DestinationFilter(destination) {
|
||||
@Override
|
||||
public void send(ProducerBrokerExchange context, Message message) throws Exception {
|
||||
// Send message to Destination
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("SimpleDestinationInterceptor: Sending message to destination:" + this.getActiveMQDestination().getPhysicalName());
|
||||
}
|
||||
// message.setDestination(destination.getActiveMQDestination());
|
||||
super.send(context, message);
|
||||
}
|
||||
};
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.activemq.broker.region.DestinationInterceptor#remove(org.apache.activemq.broker.region.Destination)
|
||||
*/
|
||||
@Override
|
||||
public void remove(Destination destination) {
|
||||
LOG.info("remove({})", destination.getName());
|
||||
this.broker = null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.activemq.broker.region.DestinationInterceptor#create(org.apache.activemq.broker.Broker, org.apache.activemq.broker.ConnectionContext, org.apache.activemq.command.ActiveMQDestination)
|
||||
*/
|
||||
@Override
|
||||
public void create(Broker broker, ConnectionContext context, ActiveMQDestination destination) throws Exception {
|
||||
LOG.info("create(" + broker.getBrokerName() + ", " + context.toString() + ", " + destination.getPhysicalName());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import org.apache.activemq.spring.ConsumerBean;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class FilteredQueueTest extends CompositeQueueTest {
|
||||
|
||||
@Override
|
||||
protected String getBrokerConfigUri() {
|
||||
return "org/apache/activemq/broker/virtual/filtered-queue.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertMessagesArrived(ConsumerBean messageList1, ConsumerBean messageList2) {
|
||||
messageList1.assertMessagesArrived(total / 2);
|
||||
messageList2.assertMessagesArrived(1);
|
||||
}
|
||||
}
|
|
@ -1,167 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.region.DestinationInterceptor;
|
||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
||||
import org.apache.activemq.broker.region.virtual.MirroredQueue;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
||||
import org.apache.activemq.usage.MemoryUsage;
|
||||
import org.apache.activemq.usage.StoreUsage;
|
||||
import org.apache.activemq.usage.SystemUsage;
|
||||
import org.apache.activemq.usage.TempUsage;
|
||||
import org.apache.activemq.util.IOHelper;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* This test will determine that the producer flow control does not kick in.
|
||||
* The original MirroredQueue implementation was causing the queue to update
|
||||
* the topic memory usage instead of the queue memory usage.
|
||||
* The reason is that the message memory usage instance will not be updated
|
||||
* unless it is null. This was the case when the message was initially sent
|
||||
* to the topic but then it was non-null when it was being sent to the queue.
|
||||
* When the region destination was set, the associated memory usage was not
|
||||
* updated to the passed queue destination and thus the memory usage of the
|
||||
* topic was being updated instead.
|
||||
*
|
||||
* @author Claudio Corsi
|
||||
*/
|
||||
public class MirroredQueueCorrectMemoryUsageTest extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MirroredQueueCorrectMemoryUsageTest.class);
|
||||
|
||||
private static final long ONE_MB = 0x0100000;
|
||||
private static final long TEN_MB = ONE_MB * 10;
|
||||
private static final long TWENTY_MB = TEN_MB * 2;
|
||||
|
||||
private static final String CREATED_STATIC_FOR_PERSISTENT = "created.static.for.persistent";
|
||||
|
||||
@Override
|
||||
protected boolean isPersistent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
// Create the broker service instance....
|
||||
BrokerService broker = super.createBroker();
|
||||
// Create and add the mirrored queue destination interceptor ....
|
||||
DestinationInterceptor[] destinationInterceptors = new DestinationInterceptor[1];
|
||||
MirroredQueue mq = new MirroredQueue();
|
||||
mq.setCopyMessage(true);
|
||||
mq.setPrefix("");
|
||||
mq.setPostfix(".qmirror");
|
||||
destinationInterceptors[0] = mq;
|
||||
broker.setDestinationInterceptors(destinationInterceptors);
|
||||
// Create the destination policy for the topics and queues
|
||||
PolicyMap policyMap = new PolicyMap();
|
||||
List<PolicyEntry> entries = new LinkedList<>();
|
||||
// Create Topic policy entry
|
||||
PolicyEntry policyEntry = new PolicyEntry();
|
||||
super.useTopic = true;
|
||||
ActiveMQDestination destination = super.createDestination(">");
|
||||
Assert.isTrue(destination.isTopic(), "Created destination was not a topic");
|
||||
policyEntry.setDestination(destination);
|
||||
policyEntry.setProducerFlowControl(true);
|
||||
policyEntry.setMemoryLimit(ONE_MB); // x10
|
||||
entries.add(policyEntry);
|
||||
// Create Queue policy entry
|
||||
policyEntry = new PolicyEntry();
|
||||
super.useTopic = false;
|
||||
destination = super.createDestination(CREATED_STATIC_FOR_PERSISTENT);
|
||||
Assert.isTrue(destination.isQueue(), "Created destination was not a queue");
|
||||
policyEntry.setDestination(destination);
|
||||
policyEntry.setProducerFlowControl(true);
|
||||
policyEntry.setMemoryLimit(TEN_MB);
|
||||
entries.add(policyEntry);
|
||||
policyMap.setPolicyEntries(entries);
|
||||
broker.setDestinationPolicy(policyMap);
|
||||
// Set destinations
|
||||
broker.setDestinations(new ActiveMQDestination[]{destination});
|
||||
// Set system usage
|
||||
SystemUsage memoryManager = new SystemUsage();
|
||||
MemoryUsage memoryUsage = new MemoryUsage();
|
||||
memoryUsage.setLimit(TEN_MB);
|
||||
memoryManager.setMemoryUsage(memoryUsage);
|
||||
StoreUsage storeUsage = new StoreUsage();
|
||||
storeUsage.setLimit(TWENTY_MB);
|
||||
memoryManager.setStoreUsage(storeUsage);
|
||||
TempUsage tempDiskUsage = new TempUsage();
|
||||
tempDiskUsage.setLimit(TEN_MB);
|
||||
memoryManager.setTempUsage(tempDiskUsage);
|
||||
broker.setSystemUsage(memoryManager);
|
||||
// Set the persistent adapter
|
||||
KahaDBPersistenceAdapter persistenceAdapter = new KahaDBPersistenceAdapter();
|
||||
persistenceAdapter.setJournalMaxFileLength((int) TEN_MB);
|
||||
// Delete all current messages...
|
||||
IOHelper.deleteFile(persistenceAdapter.getDirectory());
|
||||
broker.setPersistenceAdapter(persistenceAdapter);
|
||||
return broker;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Before
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
@After
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@Test(timeout = 40000)
|
||||
public void testNoMemoryUsageIncreaseForTopic() throws Exception {
|
||||
Connection connection = super.createConnection();
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
Destination destination = session.createQueue(CREATED_STATIC_FOR_PERSISTENT);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
char[] m = new char[1024];
|
||||
Arrays.fill(m, 'x');
|
||||
// create some messages that have 1k each
|
||||
for (int i = 1; i < 12000; i++) {
|
||||
producer.send(session.createTextMessage(new String(m)));
|
||||
logger.debug("Sent message: " + i);
|
||||
}
|
||||
producer.close();
|
||||
session.close();
|
||||
connection.stop();
|
||||
connection.close();
|
||||
}
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TemporaryQueue;
|
||||
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.region.RegionBroker;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.spring.ConsumerBean;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class MirroredQueueTest extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private static final transient Logger LOG = LoggerFactory.getLogger(MirroredQueueTest.class);
|
||||
private Connection connection;
|
||||
|
||||
public void testSendingToQueueIsMirrored() throws Exception {
|
||||
if (connection == null) {
|
||||
connection = createConnection();
|
||||
}
|
||||
connection.start();
|
||||
|
||||
ConsumerBean messageList = new ConsumerBean();
|
||||
messageList.setVerbose(true);
|
||||
|
||||
Destination consumeDestination = createConsumeDestination();
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
LOG.info("Consuming from: " + consumeDestination);
|
||||
|
||||
MessageConsumer c1 = session.createConsumer(consumeDestination);
|
||||
c1.setMessageListener(messageList);
|
||||
|
||||
// create topic producer
|
||||
ActiveMQQueue sendDestination = new ActiveMQQueue(getQueueName());
|
||||
LOG.info("Sending to: " + sendDestination);
|
||||
|
||||
MessageProducer producer = session.createProducer(sendDestination);
|
||||
assertNotNull(producer);
|
||||
|
||||
int total = 10;
|
||||
for (int i = 0; i < total; i++) {
|
||||
producer.send(session.createTextMessage("message: " + i));
|
||||
}
|
||||
|
||||
///Thread.sleep(1000000);
|
||||
|
||||
messageList.assertMessagesArrived(total);
|
||||
|
||||
LOG.info("Received: " + messageList);
|
||||
}
|
||||
|
||||
public void testTempMirroredQueuesClearDown() throws Exception {
|
||||
if (connection == null) {
|
||||
connection = createConnection();
|
||||
}
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
TemporaryQueue tempQueue = session.createTemporaryQueue();
|
||||
RegionBroker rb = (RegionBroker) broker.getBroker().getAdaptor(RegionBroker.class);
|
||||
assertTrue(rb.getDestinationMap().size() == 5);
|
||||
tempQueue.delete();
|
||||
assertTrue(rb.getDestinationMap().size() == 4);
|
||||
}
|
||||
|
||||
protected Destination createConsumeDestination() {
|
||||
return new ActiveMQTopic("VirtualTopic.Mirror." + getQueueName());
|
||||
}
|
||||
|
||||
protected String getQueueName() {
|
||||
return "My.Queue";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService answer = new BrokerService();
|
||||
answer.setUseMirroredQueues(true);
|
||||
answer.setPersistent(isPersistent());
|
||||
answer.addConnector(bindAddress);
|
||||
return answer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import javax.jms.Destination;
|
||||
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class MirroredQueueUsingVirtualTopicQueueTest extends MirroredQueueTest {
|
||||
|
||||
@Override
|
||||
protected Destination createConsumeDestination() {
|
||||
String queueName = "Consumer.A.VirtualTopic.Mirror." + getQueueName();
|
||||
return new ActiveMQQueue(queueName);
|
||||
}
|
||||
}
|
|
@ -1,200 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.jmx.QueueViewMBean;
|
||||
import org.apache.activemq.broker.region.DestinationInterceptor;
|
||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
||||
import org.apache.activemq.broker.region.virtual.CompositeTopic;
|
||||
import org.apache.activemq.broker.region.virtual.VirtualDestination;
|
||||
import org.apache.activemq.broker.region.virtual.VirtualDestinationInterceptor;
|
||||
import org.apache.activemq.command.ActiveMQBytesMessage;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
||||
import org.apache.activemq.util.ByteSequence;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VirtualDestPerfTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(VirtualDestPerfTest.class);
|
||||
public int messageSize = 5 * 1024;
|
||||
public int messageCount = 10000;
|
||||
ActiveMQTopic target = new ActiveMQTopic("target");
|
||||
BrokerService brokerService;
|
||||
ActiveMQConnectionFactory connectionFactory;
|
||||
|
||||
@Test
|
||||
@Ignore("comparison test - 'new' no wait on future with async send broker side is always on")
|
||||
public void testAsyncSendBurstToFillCache() throws Exception {
|
||||
startBroker(4, true, true);
|
||||
connectionFactory.setUseAsyncSend(true);
|
||||
|
||||
// a burst of messages to fill the cache
|
||||
messageCount = 22000;
|
||||
messageSize = 10 * 1024;
|
||||
|
||||
LinkedHashMap<Integer, Long> results = new LinkedHashMap<>();
|
||||
|
||||
final ActiveMQQueue queue = new ActiveMQQueue("targetQ");
|
||||
for (Integer numThreads : new Integer[]{1, 2}) {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
|
||||
final AtomicLong numMessagesToSend = new AtomicLong(messageCount);
|
||||
purge();
|
||||
long startTime = System.currentTimeMillis();
|
||||
for (int i = 0; i < numThreads; i++) {
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
produceMessages(numMessagesToSend, queue);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(5, TimeUnit.MINUTES);
|
||||
long endTime = System.currentTimeMillis();
|
||||
long seconds = (endTime - startTime) / 1000;
|
||||
LOG.info("For numThreads {} duration {}", numThreads.intValue(), seconds);
|
||||
results.put(numThreads, seconds);
|
||||
LOG.info("Broker got {} messages", brokerService.getAdminView().getTotalEnqueueCount());
|
||||
}
|
||||
|
||||
brokerService.stop();
|
||||
brokerService.waitUntilStopped();
|
||||
LOG.info("Results: {}", results);
|
||||
}
|
||||
|
||||
private void purge() throws Exception {
|
||||
ObjectName[] queues = brokerService.getAdminView().getQueues();
|
||||
if (queues.length == 1) {
|
||||
QueueViewMBean queueViewMBean = (QueueViewMBean) brokerService.getManagementContext().newProxyInstance(queues[0], QueueViewMBean.class, false);
|
||||
queueViewMBean.purge();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("comparison test - takes too long and really needs a peek at the graph")
|
||||
public void testPerf() throws Exception {
|
||||
LinkedHashMap<Integer, Long> resultsT = new LinkedHashMap<>();
|
||||
LinkedHashMap<Integer, Long> resultsF = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 2; i < 11; i++) {
|
||||
for (Boolean concurrent : new Boolean[]{true, false}) {
|
||||
startBroker(i, concurrent, false);
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
produceMessages(new AtomicLong(messageCount), target);
|
||||
long endTime = System.currentTimeMillis();
|
||||
long seconds = (endTime - startTime) / 1000;
|
||||
LOG.info("For routes {} duration {}", i, seconds);
|
||||
if (concurrent) {
|
||||
resultsT.put(i, seconds);
|
||||
}
|
||||
else {
|
||||
resultsF.put(i, seconds);
|
||||
}
|
||||
brokerService.stop();
|
||||
brokerService.waitUntilStopped();
|
||||
}
|
||||
}
|
||||
LOG.info("results T{} F{}", resultsT, resultsF);
|
||||
LOG.info("http://www.chartgo.com/samples.do?chart=line&border=1&show3d=0&width=600&height=500&roundedge=1&transparency=1&legend=1&title=Send:10k::Concurrent-v-Serial&xtitle=routes&ytitle=Duration(seconds)&chrtbkgndcolor=white&threshold=0.0&lang=en" + "&xaxis1=" + toStr(resultsT.keySet()) + "&yaxis1=" + toStr(resultsT.values()) + "&group1=concurrent" + "&xaxis2=" + toStr(resultsF.keySet()) + "&yaxis2=" + toStr(resultsF.values()) + "&group2=serial" + "&from=linejsp");
|
||||
}
|
||||
|
||||
private String toStr(Collection set) {
|
||||
return set.toString().replace(",", "%0D%0A").replace("[", "").replace("]", "").replace(" ", "");
|
||||
}
|
||||
|
||||
protected void produceMessages(AtomicLong messageCount, ActiveMQDestination destination) throws Exception {
|
||||
final ByteSequence payLoad = new ByteSequence(new byte[messageSize]);
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
MessageProducer messageProducer = connection.createSession(false, Session.AUTO_ACKNOWLEDGE).createProducer(destination);
|
||||
messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
ActiveMQBytesMessage message = new ActiveMQBytesMessage();
|
||||
message.setContent(payLoad);
|
||||
while (messageCount.decrementAndGet() >= 0) {
|
||||
messageProducer.send(message);
|
||||
}
|
||||
connection.close();
|
||||
}
|
||||
|
||||
private void startBroker(int fanoutCount,
|
||||
boolean concurrentSend,
|
||||
boolean concurrentStoreAndDispatchQueues) throws Exception {
|
||||
brokerService = new BrokerService();
|
||||
brokerService.setDeleteAllMessagesOnStartup(true);
|
||||
brokerService.setUseVirtualTopics(true);
|
||||
brokerService.addConnector("tcp://0.0.0.0:0");
|
||||
brokerService.setAdvisorySupport(false);
|
||||
PolicyMap destPolicyMap = new PolicyMap();
|
||||
PolicyEntry defaultEntry = new PolicyEntry();
|
||||
defaultEntry.setExpireMessagesPeriod(0);
|
||||
defaultEntry.setOptimizedDispatch(true);
|
||||
defaultEntry.setCursorMemoryHighWaterMark(110);
|
||||
destPolicyMap.setDefaultEntry(defaultEntry);
|
||||
brokerService.setDestinationPolicy(destPolicyMap);
|
||||
|
||||
CompositeTopic route = new CompositeTopic();
|
||||
route.setName("target");
|
||||
route.setForwardOnly(true);
|
||||
route.setConcurrentSend(concurrentSend);
|
||||
Collection<ActiveMQQueue> routes = new ArrayList<>();
|
||||
for (int i = 0; i < fanoutCount; i++) {
|
||||
routes.add(new ActiveMQQueue("route." + i));
|
||||
}
|
||||
route.setForwardTo(routes);
|
||||
VirtualDestinationInterceptor interceptor = new VirtualDestinationInterceptor();
|
||||
interceptor.setVirtualDestinations(new VirtualDestination[]{route});
|
||||
brokerService.setDestinationInterceptors(new DestinationInterceptor[]{interceptor});
|
||||
brokerService.start();
|
||||
|
||||
connectionFactory = new ActiveMQConnectionFactory(brokerService.getTransportConnectors().get(0).getPublishableConnectString());
|
||||
connectionFactory.setWatchTopicAdvisories(false);
|
||||
if (brokerService.getPersistenceAdapter() instanceof KahaDBPersistenceAdapter) {
|
||||
|
||||
//with parallel sends and no consumers, concurrentStoreAnd dispatch, which uses a single thread by default
|
||||
// will stop/impeed write batching. The num threads will need tweaking when consumers are in the mix but may introduce
|
||||
// order issues
|
||||
((KahaDBPersistenceAdapter) brokerService.getPersistenceAdapter()).setConcurrentStoreAndDispatchQueues(concurrentStoreAndDispatchQueues);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,433 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.ExceptionListener;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnection;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.ActiveMQMessageProducer;
|
||||
import org.apache.activemq.ActiveMQSession;
|
||||
import org.apache.activemq.RedeliveryPolicy;
|
||||
import org.apache.activemq.broker.BrokerFactory;
|
||||
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.ActiveMQQueue;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Unit test for virtual topics and DLQ messaging. See individual test for more
|
||||
* detail
|
||||
*/
|
||||
public class VirtualTopicDLQTest extends TestCase {
|
||||
|
||||
private static BrokerService broker;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(VirtualTopicDLQTest.class);
|
||||
|
||||
static final String jmsConnectionURI = "failover:(vm://localhost)";
|
||||
|
||||
// Virtual Topic that the test publishes 10 messages to
|
||||
private static final String virtualTopicName = "VirtualTopic.Test";
|
||||
|
||||
// Queues that receive all the messages send to the virtual topic
|
||||
private static final String consumer1Prefix = "Consumer.A.";
|
||||
private static final String consumer2Prefix = "Consumer.B.";
|
||||
private static final String consumer3Prefix = "Consumer.C.";
|
||||
|
||||
// Expected Individual Dead Letter Queue names that are tied to the
|
||||
// Subscriber Queues
|
||||
private static final String dlqPrefix = "ActiveMQ.DLQ.Topic.";
|
||||
|
||||
// Number of messages
|
||||
private static final int numberMessages = 6;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
try {
|
||||
broker = BrokerFactory.createBroker("xbean:org/apache/activemq/broker/virtual/virtual-individual-dlq.xml", true);
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
try {
|
||||
// Purge the DLQ's so counts are correct for next run
|
||||
purgeDestination(dlqPrefix + consumer1Prefix + virtualTopicName);
|
||||
purgeDestination(dlqPrefix + consumer2Prefix + virtualTopicName);
|
||||
purgeDestination(dlqPrefix + consumer3Prefix + virtualTopicName);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
broker = null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This test verifies that all undelivered messages sent to a consumers
|
||||
* listening on a queue associated with a virtual topic with be forwarded to
|
||||
* separate DLQ's.
|
||||
*
|
||||
* Note that the broker config, deadLetterStrategy need to have the enable
|
||||
* audit set to false so that duplicate message sent from a topic to
|
||||
* individual consumers are forwarded to the DLQ
|
||||
*
|
||||
* <deadLetterStrategy> <bean
|
||||
* xmlns="http://www.springframework.org/schema/beans"
|
||||
* class="org.apache.activemq.broker.region.policy.IndividualDeadLetterStrategy"
|
||||
* > <property name="useQueueForQueueMessages" value="true"></property>
|
||||
* <property name="processNonPersistent" value="true"></property> <property
|
||||
* name="processExpired" value="false"></property> <property
|
||||
* name="enableAudit" value="false"></property>
|
||||
*
|
||||
* </bean> </deadLetterStrategy>
|
||||
*/
|
||||
@Test
|
||||
public void testVirtualTopicSubscriberDeadLetterQueue() throws Exception {
|
||||
|
||||
TestConsumer consumer1 = null;
|
||||
TestConsumer consumer2 = null;
|
||||
TestConsumer consumer3 = null;
|
||||
TestConsumer dlqConsumer1 = null;
|
||||
TestConsumer dlqConsumer2 = null;
|
||||
TestConsumer dlqConsumer3 = null;
|
||||
|
||||
try {
|
||||
|
||||
// The first 2 consumers will rollback, ultimately causing messages
|
||||
// to land on the DLQ
|
||||
consumer1 = new TestConsumer(consumer1Prefix + virtualTopicName, false, numberMessages, true);
|
||||
thread(consumer1, false);
|
||||
|
||||
consumer2 = new TestConsumer(consumer2Prefix + virtualTopicName, false, numberMessages, true);
|
||||
thread(consumer2, false);
|
||||
|
||||
// TestConsumer that does not throw exceptions, messages should not
|
||||
// land on DLQ
|
||||
consumer3 = new TestConsumer(consumer3Prefix + virtualTopicName, false, numberMessages, false);
|
||||
thread(consumer3, false);
|
||||
|
||||
// TestConsumer to read the expected Dead Letter Queue
|
||||
dlqConsumer1 = new TestConsumer(dlqPrefix + consumer1Prefix + virtualTopicName, false, numberMessages, false);
|
||||
thread(dlqConsumer1, false);
|
||||
|
||||
dlqConsumer2 = new TestConsumer(dlqPrefix + consumer2Prefix + virtualTopicName, false, numberMessages, false);
|
||||
thread(dlqConsumer2, false);
|
||||
|
||||
dlqConsumer3 = new TestConsumer(dlqPrefix + consumer3Prefix + virtualTopicName, false, numberMessages, false);
|
||||
thread(dlqConsumer3, false);
|
||||
|
||||
// Give the consumers a second to start
|
||||
Thread.sleep(1000);
|
||||
|
||||
// Start the producer
|
||||
TestProducer producer = new TestProducer(virtualTopicName, true, numberMessages);
|
||||
thread(producer, false);
|
||||
|
||||
assertTrue("sent all producer messages in time, count is: " + producer.getLatch().getCount(), producer.getLatch().await(10, TimeUnit.SECONDS));
|
||||
LOG.info("producer successful, count = " + producer.getLatch().getCount());
|
||||
|
||||
assertTrue("remaining consumer1 count should be zero, is: " + consumer1.getLatch().getCount(), consumer1.getLatch().await(10, TimeUnit.SECONDS));
|
||||
LOG.info("consumer1 successful, count = " + consumer1.getLatch().getCount());
|
||||
|
||||
assertTrue("remaining consumer2 count should be zero, is: " + consumer2.getLatch().getCount(), consumer2.getLatch().await(10, TimeUnit.SECONDS));
|
||||
LOG.info("consumer2 successful, count = " + consumer2.getLatch().getCount());
|
||||
|
||||
assertTrue("remaining consumer3 count should be zero, is: " + consumer3.getLatch().getCount(), consumer3.getLatch().await(10, TimeUnit.SECONDS));
|
||||
LOG.info("consumer3 successful, count = " + consumer3.getLatch().getCount());
|
||||
|
||||
assertTrue("remaining dlqConsumer1 count should be zero, is: " + dlqConsumer1.getLatch().getCount(), dlqConsumer1.getLatch().await(10, TimeUnit.SECONDS));
|
||||
LOG.info("dlqConsumer1 successful, count = " + dlqConsumer1.getLatch().getCount());
|
||||
|
||||
assertTrue("remaining dlqConsumer2 count should be zero, is: " + dlqConsumer2.getLatch().getCount(), dlqConsumer2.getLatch().await(10, TimeUnit.SECONDS));
|
||||
LOG.info("dlqConsumer2 successful, count = " + dlqConsumer2.getLatch().getCount());
|
||||
|
||||
assertTrue("remaining dlqConsumer3 count should be " + numberMessages + ", is: " + dlqConsumer3.getLatch().getCount(), dlqConsumer3.getLatch().getCount() == numberMessages);
|
||||
LOG.info("dlqConsumer2 successful, count = " + dlqConsumer2.getLatch().getCount());
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
// Tell consumers to stop (don't read any more messages after this)
|
||||
if (consumer1 != null)
|
||||
consumer1.setStop(true);
|
||||
if (consumer2 != null)
|
||||
consumer2.setStop(true);
|
||||
if (consumer3 != null)
|
||||
consumer3.setStop(true);
|
||||
if (dlqConsumer1 != null)
|
||||
dlqConsumer1.setStop(true);
|
||||
if (dlqConsumer2 != null)
|
||||
dlqConsumer2.setStop(true);
|
||||
if (dlqConsumer3 != null)
|
||||
dlqConsumer3.setStop(true);
|
||||
}
|
||||
}
|
||||
|
||||
private static Thread thread(Runnable runnable, boolean daemon) {
|
||||
Thread brokerThread = new Thread(runnable);
|
||||
brokerThread.setDaemon(daemon);
|
||||
brokerThread.start();
|
||||
return brokerThread;
|
||||
}
|
||||
|
||||
private class TestProducer implements Runnable {
|
||||
|
||||
private String destinationName = null;
|
||||
private boolean isTopic = true;
|
||||
private int numberMessages = 0;
|
||||
private CountDownLatch latch = null;
|
||||
|
||||
public TestProducer(String destinationName, boolean isTopic, int numberMessages) {
|
||||
this.destinationName = destinationName;
|
||||
this.isTopic = isTopic;
|
||||
this.numberMessages = numberMessages;
|
||||
latch = new CountDownLatch(numberMessages);
|
||||
}
|
||||
|
||||
public CountDownLatch getLatch() {
|
||||
return latch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ActiveMQConnectionFactory connectionFactory = null;
|
||||
ActiveMQConnection connection = null;
|
||||
ActiveMQSession session = null;
|
||||
Destination destination = null;
|
||||
|
||||
try {
|
||||
LOG.info("Started TestProducer for destination (" + destinationName + ")");
|
||||
|
||||
connectionFactory = new ActiveMQConnectionFactory(jmsConnectionURI);
|
||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
||||
connection.start();
|
||||
session = (ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
if (isTopic) {
|
||||
destination = session.createTopic(this.destinationName);
|
||||
}
|
||||
else {
|
||||
destination = session.createQueue(this.destinationName);
|
||||
}
|
||||
|
||||
// Create a MessageProducer from the Session to the Topic or
|
||||
// Queue
|
||||
ActiveMQMessageProducer producer = (ActiveMQMessageProducer) session.createProducer(destination);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
|
||||
for (int i = 0; i < numberMessages; i++) {
|
||||
TextMessage message = session.createTextMessage("I am a message :: " + String.valueOf(i));
|
||||
try {
|
||||
producer.send(message);
|
||||
|
||||
}
|
||||
catch (Exception deeperException) {
|
||||
LOG.info("Producer for destination (" + destinationName + ") Caught: " + deeperException);
|
||||
}
|
||||
|
||||
latch.countDown();
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
|
||||
LOG.info("Finished TestProducer for destination (" + destinationName + ")");
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Terminating TestProducer(" + destinationName + ")Caught: " + e);
|
||||
e.printStackTrace();
|
||||
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
// Clean up
|
||||
if (session != null)
|
||||
session.close();
|
||||
if (connection != null)
|
||||
connection.close();
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
LOG.error("Closing connection/session (" + destinationName + ")Caught: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class TestConsumer implements Runnable, ExceptionListener, MessageListener {
|
||||
|
||||
private String destinationName = null;
|
||||
private boolean isTopic = true;
|
||||
private CountDownLatch latch = null;
|
||||
private int maxRedeliveries = 0;
|
||||
private int receivedMessageCounter = 0;
|
||||
private boolean bFakeFail = false;
|
||||
private boolean bStop = false;
|
||||
|
||||
private ActiveMQConnectionFactory connectionFactory = null;
|
||||
private ActiveMQConnection connection = null;
|
||||
private Session session = null;
|
||||
private MessageConsumer consumer = null;
|
||||
|
||||
public TestConsumer(String destinationName, boolean isTopic, int expectedNumberMessages, boolean bFakeFail) {
|
||||
this.destinationName = destinationName;
|
||||
this.isTopic = isTopic;
|
||||
latch = new CountDownLatch(expectedNumberMessages * (this.bFakeFail ? (maxRedeliveries + 1) : 1));
|
||||
this.bFakeFail = bFakeFail;
|
||||
}
|
||||
|
||||
public CountDownLatch getLatch() {
|
||||
return latch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
LOG.info("Started TestConsumer for destination (" + destinationName + ")");
|
||||
|
||||
connectionFactory = new ActiveMQConnectionFactory(jmsConnectionURI);
|
||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
||||
connection.start();
|
||||
session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
|
||||
RedeliveryPolicy policy = connection.getRedeliveryPolicy();
|
||||
policy.setInitialRedeliveryDelay(1);
|
||||
policy.setUseExponentialBackOff(false);
|
||||
policy.setMaximumRedeliveries(maxRedeliveries);
|
||||
|
||||
connection.setExceptionListener(this);
|
||||
|
||||
Destination destination = null;
|
||||
if (isTopic) {
|
||||
destination = session.createTopic(destinationName);
|
||||
}
|
||||
else {
|
||||
destination = session.createQueue(destinationName);
|
||||
}
|
||||
|
||||
consumer = session.createConsumer(destination);
|
||||
consumer.setMessageListener(this);
|
||||
|
||||
while (!bStop) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
LOG.info("Finished TestConsumer for destination name (" + destinationName + ") remaining " + this.latch.getCount() + " messages " + this.toString());
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Consumer (" + destinationName + ") Caught: " + e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
// Clean up
|
||||
if (consumer != null)
|
||||
consumer.close();
|
||||
if (session != null)
|
||||
session.close();
|
||||
if (connection != null)
|
||||
connection.close();
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
LOG.error("Closing connection/session (" + destinationName + ")Caught: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onException(JMSException ex) {
|
||||
ex.printStackTrace();
|
||||
LOG.error("Consumer for destination, (" + destinationName + "), JMS Exception occurred. Shutting down client.");
|
||||
}
|
||||
|
||||
public synchronized void setStop(boolean bStop) {
|
||||
this.bStop = bStop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onMessage(Message message) {
|
||||
receivedMessageCounter++;
|
||||
latch.countDown();
|
||||
|
||||
LOG.info("Consumer for destination (" + destinationName + ") latch countdown: " + latch.getCount() + " :: Number messages received " + this.receivedMessageCounter);
|
||||
|
||||
try {
|
||||
LOG.info("Consumer for destination (" + destinationName + ") Received message id :: " + message.getJMSMessageID());
|
||||
|
||||
if (!bFakeFail) {
|
||||
LOG.info("Consumer on destination " + destinationName + " committing JMS Session for message: " + message.toString());
|
||||
session.commit();
|
||||
}
|
||||
else {
|
||||
LOG.info("Consumer on destination " + destinationName + " rolling back JMS Session for message: " + message.toString());
|
||||
session.rollback(); // rolls back all the consumed messages
|
||||
// on the session to
|
||||
}
|
||||
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
ex.printStackTrace();
|
||||
LOG.error("Error reading JMS Message from destination " + destinationName + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void purgeDestination(String destination) throws Exception {
|
||||
final Queue dest = (Queue) ((RegionBroker) broker.getRegionBroker()).getQueueRegion().getDestinationMap().get(new ActiveMQQueue(destination));
|
||||
dest.purge();
|
||||
assertEquals(0, dest.getDestinationStatistics().getMessages().getCount());
|
||||
}
|
||||
}
|
|
@ -1,188 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
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.TextMessage;
|
||||
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.spring.ConsumerBean;
|
||||
import org.apache.activemq.xbean.XBeanBrokerFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Test case for https://issues.apache.org/jira/browse/AMQ-3004
|
||||
*/
|
||||
|
||||
public class VirtualTopicDisconnectSelectorTest extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(VirtualTopicDisconnectSelectorTest.class);
|
||||
protected Connection connection;
|
||||
|
||||
public void testVirtualTopicSelectorDisconnect() throws Exception {
|
||||
testVirtualTopicDisconnect("odd = 'no'", 3000, 1500);
|
||||
}
|
||||
|
||||
public void testVirtualTopicNoSelectorDisconnect() throws Exception {
|
||||
testVirtualTopicDisconnect(null, 3000, 3000);
|
||||
}
|
||||
|
||||
public void testVirtualTopicDisconnect(String messageSelector, int total, int expected) throws Exception {
|
||||
if (connection == null) {
|
||||
connection = createConnection();
|
||||
}
|
||||
connection.start();
|
||||
|
||||
final ConsumerBean messageList = new ConsumerBean();
|
||||
|
||||
Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
|
||||
Destination producerDestination = getProducerDestination();
|
||||
Destination destination = getConsumerDsetination();
|
||||
|
||||
LOG.info("Sending to: " + producerDestination);
|
||||
LOG.info("Consuming from: " + destination);
|
||||
|
||||
MessageConsumer consumer = createConsumer(session, destination, messageSelector);
|
||||
|
||||
MessageListener listener = new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
messageList.onMessage(message);
|
||||
try {
|
||||
message.acknowledge();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
consumer.setMessageListener(listener);
|
||||
|
||||
// create topic producer
|
||||
MessageProducer producer = session.createProducer(producerDestination);
|
||||
assertNotNull(producer);
|
||||
|
||||
int disconnectCount = total / 3;
|
||||
int reconnectCount = (total * 2) / 3;
|
||||
|
||||
for (int i = 0; i < total; i++) {
|
||||
producer.send(createMessage(session, i));
|
||||
|
||||
if (i == disconnectCount) {
|
||||
consumer.close();
|
||||
}
|
||||
if (i == reconnectCount) {
|
||||
consumer = createConsumer(session, destination, messageSelector);
|
||||
consumer.setMessageListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
assertMessagesArrived(messageList, expected, 10000);
|
||||
}
|
||||
|
||||
protected Destination getConsumerDsetination() {
|
||||
return new ActiveMQQueue("Consumer.VirtualTopic.TEST");
|
||||
}
|
||||
|
||||
protected Destination getProducerDestination() {
|
||||
return new ActiveMQTopic("VirtualTopic.TEST");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
protected MessageConsumer createConsumer(Session session,
|
||||
Destination destination,
|
||||
String messageSelector) throws JMSException {
|
||||
if (messageSelector != null) {
|
||||
return session.createConsumer(destination, messageSelector);
|
||||
}
|
||||
else {
|
||||
return session.createConsumer(destination);
|
||||
}
|
||||
}
|
||||
|
||||
protected TextMessage createMessage(Session session, int i) throws JMSException {
|
||||
TextMessage textMessage = session.createTextMessage("message: " + i);
|
||||
if (i % 2 != 0) {
|
||||
textMessage.setStringProperty("odd", "yes");
|
||||
}
|
||||
else {
|
||||
textMessage.setStringProperty("odd", "no");
|
||||
}
|
||||
textMessage.setIntProperty("i", i);
|
||||
return textMessage;
|
||||
}
|
||||
|
||||
protected void assertMessagesArrived(ConsumerBean messageList, int expected, long timeout) {
|
||||
messageList.assertMessagesArrived(expected, timeout);
|
||||
|
||||
messageList.flushMessages();
|
||||
|
||||
LOG.info("validate no other messages on queues");
|
||||
try {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
Destination destination1 = getConsumerDsetination();
|
||||
|
||||
MessageConsumer c1 = session.createConsumer(destination1, null);
|
||||
c1.setMessageListener(messageList);
|
||||
|
||||
LOG.info("send one simple message that should go to both consumers");
|
||||
MessageProducer producer = session.createProducer(getProducerDestination());
|
||||
assertNotNull(producer);
|
||||
|
||||
producer.send(session.createTextMessage("Last Message"));
|
||||
|
||||
messageList.assertMessagesArrived(1);
|
||||
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
fail("unexpeced ex while waiting for last messages: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getBrokerConfigUri() {
|
||||
return "org/apache/activemq/broker/virtual/disconnected-selector.xml";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
XBeanBrokerFactory factory = new XBeanBrokerFactory();
|
||||
BrokerService answer = factory.createBroker(new URI(getBrokerConfigUri()));
|
||||
return answer;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
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 junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.spring.ConsumerBean;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class VirtualTopicPubSubTest extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private Vector<Connection> connections = new Vector<>();
|
||||
public int ackMode = Session.AUTO_ACKNOWLEDGE;
|
||||
|
||||
public static Test suite() {
|
||||
return suite(VirtualTopicPubSubTest.class);
|
||||
}
|
||||
|
||||
public void initCombosForTestVirtualTopicCreation() {
|
||||
addCombinationValues("ackMode", new Object[]{new Integer(Session.AUTO_ACKNOWLEDGE), new Integer(Session.CLIENT_ACKNOWLEDGE)});
|
||||
}
|
||||
|
||||
private boolean doneTwice = false;
|
||||
|
||||
public void testVirtualTopicCreation() throws Exception {
|
||||
doTestVirtualTopicCreation(10);
|
||||
}
|
||||
|
||||
public void doTestVirtualTopicCreation(int total) throws Exception {
|
||||
|
||||
ConsumerBean messageList = new ConsumerBean() {
|
||||
@Override
|
||||
public synchronized void onMessage(Message message) {
|
||||
super.onMessage(message);
|
||||
if (ackMode == Session.CLIENT_ACKNOWLEDGE) {
|
||||
try {
|
||||
message.acknowledge();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
messageList.setVerbose(true);
|
||||
|
||||
String queueAName = getVirtualTopicConsumerName();
|
||||
// create consumer 'cluster'
|
||||
ActiveMQQueue queue1 = new ActiveMQQueue(queueAName);
|
||||
ActiveMQQueue queue2 = new ActiveMQQueue(queueAName);
|
||||
|
||||
Session session = createStartAndTrackConnection().createSession(false, ackMode);
|
||||
MessageConsumer c1 = session.createConsumer(queue1);
|
||||
|
||||
session = createStartAndTrackConnection().createSession(false, ackMode);
|
||||
MessageConsumer c2 = session.createConsumer(queue2);
|
||||
|
||||
c1.setMessageListener(messageList);
|
||||
c2.setMessageListener(messageList);
|
||||
|
||||
// create topic producer
|
||||
Session producerSession = createStartAndTrackConnection().createSession(false, ackMode);
|
||||
MessageProducer producer = producerSession.createProducer(new ActiveMQTopic(getVirtualTopicName()));
|
||||
assertNotNull(producer);
|
||||
|
||||
for (int i = 0; i < total; i++) {
|
||||
producer.send(producerSession.createTextMessage("message: " + i));
|
||||
}
|
||||
|
||||
messageList.assertMessagesArrived(total);
|
||||
|
||||
// do twice so we confirm messages do not get redelivered after client acknowledgement
|
||||
if (doneTwice == false) {
|
||||
doneTwice = true;
|
||||
doTestVirtualTopicCreation(0);
|
||||
}
|
||||
}
|
||||
|
||||
private Connection createStartAndTrackConnection() throws Exception {
|
||||
Connection connection = createConnection();
|
||||
connection.start();
|
||||
connections.add(connection);
|
||||
return connection;
|
||||
}
|
||||
|
||||
protected String getVirtualTopicName() {
|
||||
return "VirtualTopic.TEST";
|
||||
}
|
||||
|
||||
protected String getVirtualTopicConsumerName() {
|
||||
return "Consumer.A.VirtualTopic.TEST";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
for (Connection connection : connections) {
|
||||
connection.close();
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.xbean.XBeanBrokerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class VirtualTopicPubSubUsingXBeanTest extends VirtualTopicPubSubTest {
|
||||
|
||||
@Override
|
||||
protected String getVirtualTopicConsumerName() {
|
||||
return "VirtualTopicConsumers.ConsumerNumberOne.FOO";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getVirtualTopicName() {
|
||||
return "FOO";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
XBeanBrokerFactory factory = new XBeanBrokerFactory();
|
||||
BrokerService answer = factory.createBroker(new URI(getBrokerConfigUri()));
|
||||
|
||||
// lets disable persistence as we are a test
|
||||
answer.setPersistent(false);
|
||||
|
||||
return answer;
|
||||
}
|
||||
|
||||
protected String getBrokerConfigUri() {
|
||||
return "org/apache/activemq/broker/virtual/global-virtual-topics.xml";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
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.BrokerService;
|
||||
import org.apache.activemq.broker.region.DestinationInterceptor;
|
||||
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.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.spring.ConsumerBean;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VirtualTopicSelectorTest extends CompositeTopicTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(VirtualTopicSelectorTest.class);
|
||||
|
||||
@Override
|
||||
protected Destination getConsumer1Dsetination() {
|
||||
return new ActiveMQQueue("Consumer.1.VirtualTopic.TEST");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Destination getConsumer2Dsetination() {
|
||||
return new ActiveMQQueue("Consumer.2.VirtualTopic.TEST");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Destination getProducerDestination() {
|
||||
return new ActiveMQTopic("VirtualTopic.TEST");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertMessagesArrived(ConsumerBean messageList1, ConsumerBean messageList2) {
|
||||
messageList1.assertMessagesArrived(total / 2);
|
||||
messageList2.assertMessagesArrived(total / 2);
|
||||
|
||||
messageList1.flushMessages();
|
||||
messageList2.flushMessages();
|
||||
|
||||
LOG.info("validate no other messages on queues");
|
||||
try {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
Destination destination1 = getConsumer1Dsetination();
|
||||
Destination destination2 = getConsumer2Dsetination();
|
||||
MessageConsumer c1 = session.createConsumer(destination1, null);
|
||||
MessageConsumer c2 = session.createConsumer(destination2, null);
|
||||
c1.setMessageListener(messageList1);
|
||||
c2.setMessageListener(messageList2);
|
||||
|
||||
LOG.info("send one simple message that should go to both consumers");
|
||||
MessageProducer producer = session.createProducer(getProducerDestination());
|
||||
assertNotNull(producer);
|
||||
|
||||
producer.send(session.createTextMessage("Last Message"));
|
||||
|
||||
messageList1.assertMessagesArrived(1);
|
||||
messageList2.assertMessagesArrived(1);
|
||||
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
fail("unexpeced ex while waiting for last messages: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
// use message selectors on consumers that need to propagate up to the virtual
|
||||
// topic dispatch so that un matched messages do not linger on subscription queues
|
||||
messageSelector1 = "odd = 'yes'";
|
||||
messageSelector2 = "odd = 'no'";
|
||||
|
||||
BrokerService broker = new BrokerService();
|
||||
broker.setPersistent(false);
|
||||
|
||||
VirtualTopic virtualTopic = new VirtualTopic();
|
||||
// the new config that enables selectors on the intercepter
|
||||
virtualTopic.setSelectorAware(true);
|
||||
VirtualDestinationInterceptor interceptor = new VirtualDestinationInterceptor();
|
||||
interceptor.setVirtualDestinations(new VirtualDestination[]{virtualTopic});
|
||||
broker.setDestinationInterceptors(new DestinationInterceptor[]{interceptor});
|
||||
return broker;
|
||||
}
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.broker.virtual;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.apache.activemq.broker.jmx.MBeanTest;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.spring.ConsumerBean;
|
||||
|
||||
public class VirtualTopicsAndDurableSubsTest extends MBeanTest {
|
||||
|
||||
private Connection connection;
|
||||
|
||||
public void testVirtualTopicCreationAndDurableSubs() throws Exception {
|
||||
if (connection == null) {
|
||||
connection = createConnection();
|
||||
}
|
||||
connection.setClientID(getAClientID());
|
||||
connection.start();
|
||||
|
||||
ConsumerBean messageList = new ConsumerBean();
|
||||
messageList.setVerbose(true);
|
||||
|
||||
String queueAName = getVirtualTopicConsumerName();
|
||||
// create consumer 'cluster'
|
||||
ActiveMQQueue queue1 = new ActiveMQQueue(queueAName);
|
||||
ActiveMQQueue queue2 = new ActiveMQQueue(queueAName);
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer c1 = session.createConsumer(queue1);
|
||||
MessageConsumer c2 = session.createConsumer(queue2);
|
||||
|
||||
c1.setMessageListener(messageList);
|
||||
c2.setMessageListener(messageList);
|
||||
|
||||
// create topic producer
|
||||
MessageProducer producer = session.createProducer(new ActiveMQTopic(getVirtualTopicName()));
|
||||
assertNotNull(producer);
|
||||
|
||||
int total = 10;
|
||||
for (int i = 0; i < total; i++) {
|
||||
producer.send(session.createTextMessage("message: " + i));
|
||||
}
|
||||
messageList.assertMessagesArrived(total);
|
||||
|
||||
//Add and remove durable subscriber after using VirtualTopics
|
||||
assertCreateAndDestroyDurableSubscriptions();
|
||||
}
|
||||
|
||||
protected String getAClientID() {
|
||||
return "VirtualTopicCreationAndDurableSubs";
|
||||
}
|
||||
|
||||
protected String getVirtualTopicName() {
|
||||
return "VirtualTopic.TEST";
|
||||
}
|
||||
|
||||
protected String getVirtualTopicConsumerName() {
|
||||
return "Consumer.A.VirtualTopic.TEST";
|
||||
}
|
||||
|
||||
protected String getDurableSubscriberName() {
|
||||
return "Sub1";
|
||||
}
|
||||
|
||||
protected String getDurableSubscriberTopicName() {
|
||||
return "simple.topic";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
//Overrides test cases from MBeanTest to avoid having them run.
|
||||
@Override
|
||||
public void testMBeans() throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testMoveMessages() throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testRetryMessages() throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testMoveMessagesBySelector() throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testCopyMessagesBySelector() throws Exception {
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- this file can only be parsed using the xbean-spring library -->
|
||||
<!-- START SNIPPET: xbean -->
|
||||
<beans
|
||||
xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns: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 persistent="false" useJmx="false" xmlns="http://activemq.apache.org/schema/core">
|
||||
<destinationInterceptors>
|
||||
<virtualDestinationInterceptor>
|
||||
<virtualDestinations>
|
||||
<compositeQueue name="MY.QUEUE">
|
||||
<forwardTo>
|
||||
<queue physicalName="FOO" />
|
||||
<topic physicalName="BAR" />
|
||||
</forwardTo>
|
||||
</compositeQueue>
|
||||
</virtualDestinations>
|
||||
</virtualDestinationInterceptor>
|
||||
</destinationInterceptors>
|
||||
|
||||
</broker>
|
||||
|
||||
</beans>
|
||||
<!-- END SNIPPET: xbean -->
|
|
@ -1,47 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- this file can only be parsed using the xbean-spring library -->
|
||||
<!-- START SNIPPET: xbean -->
|
||||
<beans
|
||||
xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns: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 xmlns="http://activemq.apache.org/schema/core">
|
||||
<destinationInterceptors>
|
||||
<virtualDestinationInterceptor>
|
||||
<virtualDestinations>
|
||||
<compositeTopic name="MY.TOPIC">
|
||||
<forwardTo>
|
||||
<queue physicalName="FOO" />
|
||||
<topic physicalName="BAR" />
|
||||
</forwardTo>
|
||||
</compositeTopic>
|
||||
</virtualDestinations>
|
||||
</virtualDestinationInterceptor>
|
||||
</destinationInterceptors>
|
||||
|
||||
</broker>
|
||||
|
||||
</beans>
|
||||
<!-- END SNIPPET: xbean -->
|
|
@ -1,43 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- this file can only be parsed using the xbean-spring library -->
|
||||
<!-- START SNIPPET: xbean -->
|
||||
<beans
|
||||
xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns: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 xmlns="http://activemq.apache.org/schema/core" persistent="false">
|
||||
<destinationInterceptors>
|
||||
<virtualDestinationInterceptor>
|
||||
<virtualDestinations>
|
||||
<virtualTopic name="VirtualTopic.>" prefix="Consumer." selectorAware="true"/>
|
||||
</virtualDestinations>
|
||||
</virtualDestinationInterceptor>
|
||||
</destinationInterceptors>
|
||||
<plugins>
|
||||
<virtualSelectorCacheBrokerPlugin persistFile = "target/selectorcache.data"/>
|
||||
</plugins>
|
||||
</broker>
|
||||
</beans>
|
||||
<!-- END SNIPPET: xbean -->
|
|
@ -1,47 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- this file can only be parsed using the xbean-spring library -->
|
||||
<!-- START SNIPPET: xbean -->
|
||||
<beans
|
||||
xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns: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 xmlns="http://activemq.apache.org/schema/core">
|
||||
<destinationInterceptors>
|
||||
<virtualDestinationInterceptor>
|
||||
<virtualDestinations>
|
||||
<compositeQueue name="MY.QUEUE">
|
||||
<forwardTo>
|
||||
<filteredDestination selector="odd = 'yes'" queue="FOO"/>
|
||||
<filteredDestination selector="i = 5" topic="BAR"/>
|
||||
</forwardTo>
|
||||
</compositeQueue>
|
||||
</virtualDestinations>
|
||||
</virtualDestinationInterceptor>
|
||||
</destinationInterceptors>
|
||||
|
||||
</broker>
|
||||
|
||||
</beans>
|
||||
<!-- END SNIPPET: xbean -->
|
|
@ -1,80 +0,0 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<!-- START SNIPPET: example -->
|
||||
<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">
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
The <broker> element is used to configure the ActiveMQ broker.
|
||||
-->
|
||||
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="bcBroker">
|
||||
|
||||
<destinationInterceptors>
|
||||
<virtualDestinationInterceptor>
|
||||
<virtualDestinations>
|
||||
<virtualTopic name="VirtualTopic.>" prefix="Consumer.*." />
|
||||
</virtualDestinations>
|
||||
</virtualDestinationInterceptor>
|
||||
</destinationInterceptors>
|
||||
|
||||
<destinationPolicy>
|
||||
<policyMap>
|
||||
<policyEntries>
|
||||
<policyEntry queue=">" memoryLimit="128 mb" >
|
||||
<deadLetterStrategy>
|
||||
<bean xmlns="http://www.springframework.org/schema/beans"
|
||||
class="org.apache.activemq.broker.region.policy.IndividualDeadLetterStrategy">
|
||||
<property name="useQueueForQueueMessages" value="true"></property>
|
||||
<property name="processNonPersistent" value="true"></property>
|
||||
<property name="processExpired" value="false"></property>
|
||||
<property name="enableAudit" value="false"></property>
|
||||
|
||||
</bean>
|
||||
</deadLetterStrategy>
|
||||
</policyEntry>
|
||||
<policyEntry topic=">" memoryLimit="128 mb" >
|
||||
<deadLetterStrategy>
|
||||
<bean xmlns="http://www.springframework.org/schema/beans"
|
||||
class="org.apache.activemq.broker.region.policy.IndividualDeadLetterStrategy">
|
||||
<property name="useQueueForQueueMessages" value="true"></property>
|
||||
<property name="processNonPersistent" value="true"></property>
|
||||
<property name="processExpired" value="false"></property>
|
||||
<property name="enableAudit" value="false"></property>
|
||||
|
||||
</bean>
|
||||
</deadLetterStrategy>
|
||||
</policyEntry>
|
||||
</policyEntries>
|
||||
</policyMap>
|
||||
</destinationPolicy>
|
||||
|
||||
<managementContext>
|
||||
<managementContext createConnector="false"/>
|
||||
</managementContext>
|
||||
|
||||
</broker>
|
||||
|
||||
|
||||
|
||||
</beans>
|
||||
<!-- END SNIPPET: example -->
|
|
@ -1,50 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- this file can only be parsed using the xbean-spring library -->
|
||||
<!-- 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 xmlns="http://activemq.apache.org/schema/core" persistent="false">
|
||||
|
||||
|
||||
<destinationInterceptors>
|
||||
<!-- custom destination interceptor -->
|
||||
<bean xmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.broker.virtual.DestinationInterceptorDurableSubTest$SimpleDestinationInterceptor" />
|
||||
|
||||
<virtualDestinationInterceptor>
|
||||
<virtualDestinations>
|
||||
<virtualTopic name=">" prefix="VirtualTopicConsumers.*." selectorAware="false"/>
|
||||
</virtualDestinations>
|
||||
</virtualDestinationInterceptor>
|
||||
</destinationInterceptors>
|
||||
|
||||
<managementContext>
|
||||
<managementContext createConnector="true" connectorPort="1299"/>
|
||||
</managementContext>
|
||||
</broker>
|
||||
|
||||
</beans>
|
||||
<!-- END SNIPPET: xbean -->
|
|
@ -1,206 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.MapMessage;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
|
||||
/**
|
||||
* An AMQ-1282 Test
|
||||
*/
|
||||
public class AMQ1282 extends TestCase {
|
||||
|
||||
private ConnectionFactory factory;
|
||||
private Connection connection;
|
||||
private MapMessage message;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
factory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
|
||||
connection = factory.createConnection();
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
message = session.createMapMessage();
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
connection.close();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testUnmappedBooleanMessage() throws JMSException {
|
||||
Object expected;
|
||||
try {
|
||||
expected = Boolean.valueOf(null);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
expected = ex;
|
||||
}
|
||||
try {
|
||||
Boolean actual = message.getBoolean("foo");
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
assertEquals(expected, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnmappedIntegerMessage() throws JMSException {
|
||||
Object expected;
|
||||
try {
|
||||
expected = Integer.valueOf(null);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
expected = ex;
|
||||
}
|
||||
try {
|
||||
Integer actual = message.getInt("foo");
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Class<?> aClass = expected.getClass();
|
||||
assertTrue(aClass.isInstance(ex));
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnmappedShortMessage() throws JMSException {
|
||||
Object expected;
|
||||
try {
|
||||
expected = Short.valueOf(null);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
expected = ex;
|
||||
}
|
||||
try {
|
||||
Short actual = message.getShort("foo");
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Class<?> aClass = expected.getClass();
|
||||
assertTrue(aClass.isInstance(ex));
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnmappedLongMessage() throws JMSException {
|
||||
Object expected;
|
||||
try {
|
||||
expected = Long.valueOf(null);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
expected = ex;
|
||||
}
|
||||
try {
|
||||
Long actual = message.getLong("foo");
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Class<?> aClass = expected.getClass();
|
||||
assertTrue(aClass.isInstance(ex));
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnmappedStringMessage() throws JMSException {
|
||||
Object expected;
|
||||
try {
|
||||
expected = String.valueOf(null);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
expected = ex;
|
||||
}
|
||||
try {
|
||||
String actual = message.getString("foo");
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Class<?> aClass = expected.getClass();
|
||||
assertTrue(aClass.isInstance(ex));
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnmappedCharMessage() throws JMSException {
|
||||
try {
|
||||
message.getChar("foo");
|
||||
fail("should have thrown NullPointerException");
|
||||
}
|
||||
catch (NullPointerException success) {
|
||||
assertNotNull(success);
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnmappedByteMessage() throws JMSException {
|
||||
Object expected;
|
||||
try {
|
||||
expected = Byte.valueOf(null);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
expected = ex;
|
||||
}
|
||||
try {
|
||||
Byte actual = message.getByte("foo");
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Class<?> aClass = expected.getClass();
|
||||
assertTrue(aClass.isInstance(ex));
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnmappedDoubleMessage() throws JMSException {
|
||||
Object expected;
|
||||
try {
|
||||
expected = Double.valueOf(null);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
expected = ex;
|
||||
}
|
||||
try {
|
||||
Double actual = message.getDouble("foo");
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Class<?> aClass = expected.getClass();
|
||||
assertTrue(aClass.isInstance(ex));
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnmappedFloatMessage() throws JMSException {
|
||||
Object expected;
|
||||
try {
|
||||
expected = Float.valueOf(null);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
expected = ex;
|
||||
}
|
||||
try {
|
||||
Float actual = message.getFloat("foo");
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Class<?> aClass = expected.getClass();
|
||||
assertTrue(aClass.isInstance(ex));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.spring.ConsumerBean;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class AMQ1687Test extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private Connection connection;
|
||||
|
||||
@Override
|
||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
||||
//prefetch change is not required, but test will not fail w/o it, only spew errors in the AMQ log.
|
||||
return new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getPublishableConnectString() + "?jms.prefetchPolicy.all=5");
|
||||
}
|
||||
|
||||
public void testVirtualTopicCreation() throws Exception {
|
||||
if (connection == null) {
|
||||
connection = createConnection();
|
||||
}
|
||||
connection.start();
|
||||
|
||||
ConsumerBean messageList = new ConsumerBean();
|
||||
messageList.setVerbose(true);
|
||||
|
||||
String queueAName = getVirtualTopicConsumerName();
|
||||
String queueBName = getVirtualTopicConsumerNameB();
|
||||
|
||||
// create consumer 'cluster'
|
||||
ActiveMQQueue queue1 = new ActiveMQQueue(queueAName);
|
||||
ActiveMQQueue queue2 = new ActiveMQQueue(queueBName);
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer c1 = session.createConsumer(queue1);
|
||||
MessageConsumer c2 = session.createConsumer(queue2);
|
||||
|
||||
c1.setMessageListener(messageList);
|
||||
c2.setMessageListener(messageList);
|
||||
|
||||
// create topic producer
|
||||
ActiveMQTopic topic = new ActiveMQTopic(getVirtualTopicName());
|
||||
MessageProducer producer = session.createProducer(topic);
|
||||
assertNotNull(producer);
|
||||
|
||||
int total = 100;
|
||||
for (int i = 0; i < total; i++) {
|
||||
producer.send(session.createTextMessage("message: " + i));
|
||||
}
|
||||
|
||||
messageList.assertMessagesArrived(total * 2);
|
||||
}
|
||||
|
||||
protected String getVirtualTopicName() {
|
||||
return "VirtualTopic.TEST";
|
||||
}
|
||||
|
||||
protected String getVirtualTopicConsumerName() {
|
||||
return "Consumer.A.VirtualTopic.TEST";
|
||||
}
|
||||
|
||||
protected String getVirtualTopicConsumerNameB() {
|
||||
return "Consumer.B.VirtualTopic.TEST";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
this.bindAddress = "tcp://localhost:0";
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
|
@ -1,378 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.ExceptionListener;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnection;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.ActiveMQMessageProducer;
|
||||
import org.apache.activemq.ActiveMQSession;
|
||||
import org.apache.activemq.RedeliveryPolicy;
|
||||
import org.apache.activemq.broker.BrokerFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.util.Wait;
|
||||
import org.apache.activemq.util.Wait.Condition;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Test validates that the AMQ consumer blocks on redelivery of a message,
|
||||
* through all redeliveries, until the message is either successfully consumed
|
||||
* or sent to the DLQ.
|
||||
*/
|
||||
public class AMQ1853Test {
|
||||
|
||||
private static BrokerService broker;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AMQ1853Test.class);
|
||||
static final String jmsConnectionURI = "failover:(vm://localhost)";
|
||||
|
||||
// Virtual Topic that the test publishes 10 messages to
|
||||
private static final String queueFail = "Queue.BlockingConsumer.QueueFail";
|
||||
|
||||
// Number of messages
|
||||
|
||||
private final int producerMessages = 5;
|
||||
private final int totalNumberMessages = producerMessages * 2;
|
||||
private final int maxRedeliveries = 2;
|
||||
private final int redeliveryDelay = 1000;
|
||||
|
||||
private Map<String, AtomicInteger> messageList = null;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
broker = BrokerFactory.createBroker(new URI("broker:()/localhost?persistent=false"));
|
||||
broker.setUseJmx(false);
|
||||
broker.setDeleteAllMessagesOnStartup(true);
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
broker = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsumerMessagesAreNotOrdered() throws Exception {
|
||||
|
||||
TestConsumer consumerAllFail = null;
|
||||
messageList = new Hashtable<>();
|
||||
|
||||
try {
|
||||
|
||||
// The first 2 consumers will rollback, ultimately causing messages to land on the DLQ
|
||||
|
||||
TestProducer producerAllFail = new TestProducer(queueFail);
|
||||
thread(producerAllFail, false);
|
||||
|
||||
consumerAllFail = new TestConsumer(queueFail, true);
|
||||
thread(consumerAllFail, false);
|
||||
|
||||
// Give the consumers a second to start
|
||||
Thread.sleep(1000);
|
||||
|
||||
thread(producerAllFail, false);
|
||||
|
||||
// Give the consumers a second to start
|
||||
Thread.sleep(1000);
|
||||
|
||||
producerAllFail.getLatch().await();
|
||||
|
||||
LOG.info("producer successful, count = " + producerAllFail.getLatch().getCount());
|
||||
LOG.info("final message list size = " + messageList.size());
|
||||
|
||||
assertTrue("message list size = " + messageList.size() + " exptected:" + totalNumberMessages, Wait.waitFor(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return totalNumberMessages == messageList.size();
|
||||
}
|
||||
}));
|
||||
|
||||
consumerAllFail.getLatch().await();
|
||||
|
||||
LOG.info("consumerAllFail successful, count = " + consumerAllFail.getLatch().getCount());
|
||||
|
||||
Iterator<String> keys = messageList.keySet().iterator();
|
||||
for (AtomicInteger counter : messageList.values()) {
|
||||
String message = keys.next();
|
||||
LOG.info("final count for message " + message + " counter = " + counter.get());
|
||||
assertTrue("for message " + message + " counter = " + counter.get(), counter.get() == maxRedeliveries + 1);
|
||||
}
|
||||
|
||||
assertFalse(consumerAllFail.messageReceiptIsOrdered());
|
||||
}
|
||||
finally {
|
||||
if (consumerAllFail != null) {
|
||||
consumerAllFail.setStop(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Thread thread(Runnable runnable, boolean daemon) {
|
||||
Thread brokerThread = new Thread(runnable);
|
||||
brokerThread.setDaemon(daemon);
|
||||
brokerThread.start();
|
||||
return brokerThread;
|
||||
}
|
||||
|
||||
private class TestProducer implements Runnable {
|
||||
|
||||
private CountDownLatch latch = null;
|
||||
private String destinationName = null;
|
||||
|
||||
public TestProducer(String destinationName) {
|
||||
this.destinationName = destinationName;
|
||||
// We run the producer 2 times
|
||||
latch = new CountDownLatch(totalNumberMessages);
|
||||
}
|
||||
|
||||
public CountDownLatch getLatch() {
|
||||
return latch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
ActiveMQConnectionFactory connectionFactory = null;
|
||||
ActiveMQConnection connection = null;
|
||||
ActiveMQSession session = null;
|
||||
Destination destination = null;
|
||||
|
||||
try {
|
||||
LOG.info("Started TestProducer for destination (" + destinationName + ")");
|
||||
|
||||
connectionFactory = new ActiveMQConnectionFactory(jmsConnectionURI);
|
||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
||||
connection.setCopyMessageOnSend(false);
|
||||
connection.start();
|
||||
session = (ActiveMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
destination = session.createQueue(this.destinationName);
|
||||
|
||||
// Create a MessageProducer from the Session to the Topic or Queue
|
||||
ActiveMQMessageProducer producer = (ActiveMQMessageProducer) session.createProducer(destination);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
|
||||
for (int i = 0; i < (producerMessages); i++) {
|
||||
TextMessage message = session.createTextMessage();
|
||||
message.setLongProperty("TestTime", (System.currentTimeMillis()));
|
||||
try {
|
||||
producer.send(message);
|
||||
LOG.info("Producer (" + destinationName + ")\n" + message.getJMSMessageID() + " = sent messageId\n");
|
||||
|
||||
latch.countDown();
|
||||
LOG.info(" Latch count " + latch.getCount());
|
||||
LOG.info("Producer message list size = " + messageList.keySet().size());
|
||||
messageList.put(message.getJMSMessageID(), new AtomicInteger(0));
|
||||
LOG.info("Producer message list size = " + messageList.keySet().size());
|
||||
|
||||
}
|
||||
catch (Exception deeperException) {
|
||||
LOG.info("Producer for destination (" + destinationName + ") Caught: " + deeperException);
|
||||
}
|
||||
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
|
||||
LOG.info("Finished TestProducer for destination (" + destinationName + ")");
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Terminating TestProducer(" + destinationName + ")Caught: " + e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (session != null) {
|
||||
session.close();
|
||||
}
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Closing connection/session (" + destinationName + ")Caught: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class TestConsumer implements Runnable, ExceptionListener, MessageListener {
|
||||
|
||||
private CountDownLatch latch = null;
|
||||
private int receivedMessageCounter = 0;
|
||||
private boolean bFakeFail = false;
|
||||
String destinationName = null;
|
||||
boolean bMessageReceiptIsOrdered = true;
|
||||
boolean bStop = false;
|
||||
String previousMessageId = null;
|
||||
|
||||
private ActiveMQConnectionFactory connectionFactory = null;
|
||||
private ActiveMQConnection connection = null;
|
||||
private Session session = null;
|
||||
private MessageConsumer consumer = null;
|
||||
|
||||
public TestConsumer(String destinationName, boolean bFakeFail) {
|
||||
this.bFakeFail = bFakeFail;
|
||||
latch = new CountDownLatch(totalNumberMessages * (this.bFakeFail ? (maxRedeliveries + 1) : 1));
|
||||
this.destinationName = destinationName;
|
||||
}
|
||||
|
||||
public CountDownLatch getLatch() {
|
||||
return latch;
|
||||
}
|
||||
|
||||
public boolean messageReceiptIsOrdered() {
|
||||
return bMessageReceiptIsOrdered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
LOG.info("Started TestConsumer for destination (" + destinationName + ")");
|
||||
|
||||
connectionFactory = new ActiveMQConnectionFactory(jmsConnectionURI);
|
||||
connection = (ActiveMQConnection) connectionFactory.createConnection();
|
||||
connection.setNonBlockingRedelivery(true);
|
||||
session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
|
||||
RedeliveryPolicy policy = connection.getRedeliveryPolicy();
|
||||
policy.setInitialRedeliveryDelay(redeliveryDelay);
|
||||
policy.setBackOffMultiplier(-1);
|
||||
policy.setRedeliveryDelay(redeliveryDelay);
|
||||
policy.setMaximumRedeliveryDelay(-1);
|
||||
policy.setUseExponentialBackOff(false);
|
||||
policy.setMaximumRedeliveries(maxRedeliveries);
|
||||
|
||||
connection.setExceptionListener(this);
|
||||
Destination destination = session.createQueue(destinationName);
|
||||
consumer = session.createConsumer(destination);
|
||||
consumer.setMessageListener(this);
|
||||
|
||||
connection.start();
|
||||
|
||||
while (!bStop) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
LOG.info("Finished TestConsumer for destination name (" + destinationName + ") remaining " + this.latch.getCount() + " messages " + this.toString());
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Consumer (" + destinationName + ") Caught: " + e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (consumer != null) {
|
||||
consumer.close();
|
||||
}
|
||||
if (session != null) {
|
||||
session.close();
|
||||
}
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Closing connection/session (" + destinationName + ")Caught: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onException(JMSException ex) {
|
||||
LOG.error("Consumer for destination, (" + destinationName + "), JMS Exception occurred. Shutting down client.");
|
||||
}
|
||||
|
||||
public synchronized void setStop(boolean bStop) {
|
||||
this.bStop = bStop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onMessage(Message message) {
|
||||
receivedMessageCounter++;
|
||||
latch.countDown();
|
||||
|
||||
LOG.info("Consumer for destination (" + destinationName + ") latch countdown: " + latch.getCount() +
|
||||
" :: Number messages received " + this.receivedMessageCounter);
|
||||
|
||||
try {
|
||||
|
||||
if (receivedMessageCounter % (maxRedeliveries + 1) == 1) {
|
||||
previousMessageId = message.getJMSMessageID();
|
||||
}
|
||||
|
||||
if (bMessageReceiptIsOrdered) {
|
||||
bMessageReceiptIsOrdered = previousMessageId.trim().equals(message.getJMSMessageID());
|
||||
}
|
||||
|
||||
final String jmsMessageId = message.getJMSMessageID();
|
||||
assertTrue("Did not find expected ", Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return messageList.containsKey(jmsMessageId);
|
||||
}
|
||||
}));
|
||||
|
||||
AtomicInteger counter = messageList.get(jmsMessageId);
|
||||
counter.incrementAndGet();
|
||||
|
||||
LOG.info("Consumer for destination (" + destinationName + ")\n" + message.getJMSMessageID() + " = currentMessageId\n" + previousMessageId + " = previousMessageId\n" + bMessageReceiptIsOrdered + "= bMessageReceiptIsOrdered\n" + ">>LATENCY " + (System.currentTimeMillis() - message.getLongProperty("TestTime")) + "\n" + "message counter = " + counter.get());
|
||||
|
||||
if (!bFakeFail) {
|
||||
LOG.debug("Consumer on destination " + destinationName + " committing JMS Session for message: " + message.toString());
|
||||
session.commit();
|
||||
}
|
||||
else {
|
||||
LOG.debug("Consumer on destination " + destinationName + " rolling back JMS Session for message: " + message.toString());
|
||||
session.rollback(); // rolls back all the consumed messages on the session to
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
LOG.error("Error reading JMS Message from destination " + destinationName + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,233 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
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;
|
||||
import org.apache.activemq.leveldb.LevelDBStore;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This is a test case for the issue reported at:
|
||||
* https://issues.apache.org/activemq/browse/AMQ-1866
|
||||
*
|
||||
* If you have a JMS producer sending messages to multiple fast consumers and
|
||||
* one slow consumer, eventually all consumers will run as slow as
|
||||
* the slowest consumer.
|
||||
*/
|
||||
public class AMQ1866 extends TestCase {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ConsumerThread.class);
|
||||
private BrokerService brokerService;
|
||||
private ArrayList<Thread> threads = new ArrayList<>();
|
||||
|
||||
private final String ACTIVEMQ_BROKER_BIND = "tcp://localhost:0";
|
||||
private String ACTIVEMQ_BROKER_URI;
|
||||
|
||||
AtomicBoolean shutdown = new AtomicBoolean();
|
||||
private ActiveMQQueue destination;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
// Start an embedded broker up.
|
||||
brokerService = new BrokerService();
|
||||
LevelDBStore adaptor = new LevelDBStore();
|
||||
brokerService.setPersistenceAdapter(adaptor);
|
||||
brokerService.deleteAllMessages();
|
||||
|
||||
// A small max page size makes this issue occur faster.
|
||||
PolicyMap policyMap = new PolicyMap();
|
||||
PolicyEntry pe = new PolicyEntry();
|
||||
pe.setMaxPageSize(1);
|
||||
policyMap.put(new ActiveMQQueue(">"), pe);
|
||||
brokerService.setDestinationPolicy(policyMap);
|
||||
|
||||
brokerService.addConnector(ACTIVEMQ_BROKER_BIND);
|
||||
brokerService.start();
|
||||
|
||||
ACTIVEMQ_BROKER_URI = brokerService.getTransportConnectors().get(0).getPublishableConnectString();
|
||||
destination = new ActiveMQQueue(getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
// Stop any running threads.
|
||||
shutdown.set(true);
|
||||
for (Thread t : threads) {
|
||||
t.interrupt();
|
||||
t.join();
|
||||
}
|
||||
brokerService.stop();
|
||||
}
|
||||
|
||||
public void testConsumerSlowDownPrefetch0() throws Exception {
|
||||
ACTIVEMQ_BROKER_URI = ACTIVEMQ_BROKER_URI + "?jms.prefetchPolicy.queuePrefetch=0";
|
||||
doTestConsumerSlowDown();
|
||||
}
|
||||
|
||||
public void testConsumerSlowDownPrefetch10() throws Exception {
|
||||
ACTIVEMQ_BROKER_URI = ACTIVEMQ_BROKER_URI + "?jms.prefetchPolicy.queuePrefetch=10";
|
||||
doTestConsumerSlowDown();
|
||||
}
|
||||
|
||||
public void testConsumerSlowDownDefaultPrefetch() throws Exception {
|
||||
doTestConsumerSlowDown();
|
||||
}
|
||||
|
||||
public void doTestConsumerSlowDown() throws Exception {
|
||||
|
||||
// Preload the queue.
|
||||
produce(20000);
|
||||
|
||||
Thread producer = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!shutdown.get()) {
|
||||
produce(1000);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
};
|
||||
threads.add(producer);
|
||||
producer.start();
|
||||
|
||||
// This is the slow consumer.
|
||||
ConsumerThread c1 = new ConsumerThread("Consumer-1");
|
||||
threads.add(c1);
|
||||
c1.start();
|
||||
|
||||
// Wait a bit so that the slow consumer gets assigned most of the messages.
|
||||
Thread.sleep(500);
|
||||
ConsumerThread c2 = new ConsumerThread("Consumer-2");
|
||||
threads.add(c2);
|
||||
c2.start();
|
||||
|
||||
int totalReceived = 0;
|
||||
for (int i = 0; i < 30; i++) {
|
||||
Thread.sleep(1000);
|
||||
long c1Counter = c1.counter.getAndSet(0);
|
||||
long c2Counter = c2.counter.getAndSet(0);
|
||||
log.debug("c1: " + c1Counter + ", c2: " + c2Counter);
|
||||
totalReceived += c1Counter;
|
||||
totalReceived += c2Counter;
|
||||
|
||||
// Once message have been flowing for a few seconds, start asserting that c2 always gets messages. It should be receiving about 100 / sec
|
||||
if (i > 10) {
|
||||
assertTrue("Total received=" + totalReceived + ", Consumer 2 should be receiving new messages every second.", c2Counter > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void produce(int count) throws Exception {
|
||||
Connection connection = null;
|
||||
try {
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(ACTIVEMQ_BROKER_URI);
|
||||
factory.setDispatchAsync(true);
|
||||
|
||||
connection = factory.createConnection();
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
connection.start();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
producer.send(session.createTextMessage(getName() + " Message " + (++i)));
|
||||
}
|
||||
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
connection.close();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ConsumerThread extends Thread {
|
||||
|
||||
final AtomicLong counter = new AtomicLong();
|
||||
|
||||
public ConsumerThread(String threadId) {
|
||||
super(threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Connection connection = null;
|
||||
try {
|
||||
log.debug(getName() + ": is running");
|
||||
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(ACTIVEMQ_BROKER_URI);
|
||||
factory.setDispatchAsync(true);
|
||||
|
||||
connection = factory.createConnection();
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
connection.start();
|
||||
|
||||
while (!shutdown.get()) {
|
||||
TextMessage msg = (TextMessage) consumer.receive(1000);
|
||||
if (msg != null) {
|
||||
int sleepingTime;
|
||||
if (getName().equals("Consumer-1")) {
|
||||
sleepingTime = 1000 * 1000;
|
||||
}
|
||||
else {
|
||||
sleepingTime = 1;
|
||||
}
|
||||
counter.incrementAndGet();
|
||||
Thread.sleep(sleepingTime);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
finally {
|
||||
log.debug(getName() + ": is stopping");
|
||||
try {
|
||||
connection.close();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,192 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
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 java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class AMQ1893Test extends TestCase {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AMQ1893Test.class);
|
||||
|
||||
static final String QUEUE_NAME = "TEST";
|
||||
|
||||
static final int MESSAGE_COUNT_OF_ONE_GROUP = 10000;
|
||||
|
||||
static final int[] PRIORITIES = new int[]{0, 5, 10};
|
||||
|
||||
static final boolean debug = false;
|
||||
|
||||
private BrokerService brokerService;
|
||||
|
||||
private ActiveMQQueue destination;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
brokerService = new BrokerService();
|
||||
brokerService.setDeleteAllMessagesOnStartup(true);
|
||||
brokerService.addConnector("tcp://localhost:0");
|
||||
brokerService.start();
|
||||
destination = new ActiveMQQueue(QUEUE_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
// Stop any running threads.
|
||||
brokerService.stop();
|
||||
}
|
||||
|
||||
public void testProduceConsumeWithSelector() throws Exception {
|
||||
new TestProducer().produceMessages();
|
||||
new TestConsumer().consume();
|
||||
}
|
||||
|
||||
class TestProducer {
|
||||
|
||||
public void produceMessages() throws Exception {
|
||||
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerService.getTransportConnectors().get(0).getConnectUri().toString());
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Destination destination = session.createQueue(QUEUE_NAME);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
for (int priority : PRIORITIES) {
|
||||
|
||||
String name = null;
|
||||
if (priority == 10) {
|
||||
name = "high";
|
||||
}
|
||||
else if (priority == 5) {
|
||||
name = "mid";
|
||||
}
|
||||
else {
|
||||
name = "low";
|
||||
}
|
||||
|
||||
for (int i = 1; i <= MESSAGE_COUNT_OF_ONE_GROUP; i++) {
|
||||
|
||||
TextMessage message = session.createTextMessage(name + "_" + i);
|
||||
message.setIntProperty("priority", priority);
|
||||
|
||||
producer.send(message);
|
||||
}
|
||||
}
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
log.info("sent " + (MESSAGE_COUNT_OF_ONE_GROUP * 3) + " messages in " + (end - start) + " ms");
|
||||
|
||||
producer.close();
|
||||
session.close();
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
class TestConsumer {
|
||||
|
||||
private CountDownLatch finishLatch = new CountDownLatch(1);
|
||||
|
||||
public void consume() throws Exception {
|
||||
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerService.getTransportConnectors().get(0).getConnectUri().toString());
|
||||
|
||||
final int totalMessageCount = MESSAGE_COUNT_OF_ONE_GROUP * PRIORITIES.length;
|
||||
final AtomicInteger counter = new AtomicInteger();
|
||||
final MessageListener listener = new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
|
||||
if (debug) {
|
||||
try {
|
||||
log.info(((TextMessage) message).getText());
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (counter.incrementAndGet() == totalMessageCount) {
|
||||
|
||||
finishLatch.countDown();
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int consumerCount = PRIORITIES.length;
|
||||
Connection[] connections = new Connection[consumerCount];
|
||||
Session[] sessions = new Session[consumerCount];
|
||||
MessageConsumer[] consumers = new MessageConsumer[consumerCount];
|
||||
|
||||
for (int i = 0; i < consumerCount; i++) {
|
||||
String selector = "priority = " + PRIORITIES[i];
|
||||
|
||||
connections[i] = connectionFactory.createConnection();
|
||||
sessions[i] = connections[i].createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
consumers[i] = sessions[i].createConsumer(destination, selector);
|
||||
consumers[i].setMessageListener(listener);
|
||||
}
|
||||
|
||||
for (Connection connection : connections) {
|
||||
connection.start();
|
||||
}
|
||||
|
||||
log.info("received " + counter.get() + " messages");
|
||||
|
||||
assertTrue("got all messages in time", finishLatch.await(60, TimeUnit.SECONDS));
|
||||
|
||||
log.info("received " + counter.get() + " messages");
|
||||
|
||||
for (MessageConsumer consumer : consumers) {
|
||||
consumer.close();
|
||||
}
|
||||
|
||||
for (Session session : sessions) {
|
||||
session.close();
|
||||
}
|
||||
|
||||
for (Connection connection : connections) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,229 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
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.TextMessage;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
|
||||
public class AMQ1917Test extends TestCase {
|
||||
|
||||
private static final int NUM_MESSAGES = 4000;
|
||||
private static final int NUM_THREADS = 10;
|
||||
private static final String REQUEST_QUEUE = "mock.in.queue";
|
||||
private static final String REPLY_QUEUE = "mock.out.queue";
|
||||
|
||||
private Destination requestDestination = ActiveMQDestination.createDestination(REQUEST_QUEUE, ActiveMQDestination.QUEUE_TYPE);
|
||||
private Destination replyDestination = ActiveMQDestination.createDestination(REPLY_QUEUE, ActiveMQDestination.QUEUE_TYPE);
|
||||
|
||||
private CountDownLatch roundTripLatch = new CountDownLatch(NUM_MESSAGES);
|
||||
private CountDownLatch errorLatch = new CountDownLatch(1);
|
||||
private ThreadPoolExecutor tpe;
|
||||
private final String BROKER_URL = "tcp://localhost:0";
|
||||
private String connectionUri;
|
||||
private BrokerService broker = null;
|
||||
private boolean working = true;
|
||||
|
||||
// trival session/producer pool
|
||||
final Session[] sessions = new Session[NUM_THREADS];
|
||||
final MessageProducer[] producers = new MessageProducer[NUM_THREADS];
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
broker = new BrokerService();
|
||||
broker.setPersistent(false);
|
||||
broker.addConnector(BROKER_URL);
|
||||
broker.start();
|
||||
|
||||
connectionUri = broker.getTransportConnectors().get(0).getPublishableConnectString();
|
||||
|
||||
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(10000);
|
||||
tpe = new ThreadPoolExecutor(NUM_THREADS, NUM_THREADS, 60000, TimeUnit.MILLISECONDS, queue);
|
||||
ThreadFactory limitedthreadFactory = new LimitedThreadFactory(tpe.getThreadFactory());
|
||||
tpe.setThreadFactory(limitedthreadFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
broker.stop();
|
||||
tpe.shutdown();
|
||||
}
|
||||
|
||||
public void testLoadedSendReceiveWithCorrelationId() throws Exception {
|
||||
|
||||
ActiveMQConnectionFactory connectionFactory = new org.apache.activemq.ActiveMQConnectionFactory();
|
||||
connectionFactory.setBrokerURL(connectionUri);
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
setupReceiver(connection);
|
||||
|
||||
connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
|
||||
// trival session/producer pool
|
||||
for (int i = 0; i < NUM_THREADS; i++) {
|
||||
sessions[i] = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
producers[i] = sessions[i].createProducer(requestDestination);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_MESSAGES; i++) {
|
||||
MessageSenderReceiver msr = new MessageSenderReceiver(requestDestination, replyDestination, "Test Message : " + i);
|
||||
tpe.execute(msr);
|
||||
}
|
||||
|
||||
while (!roundTripLatch.await(4000, TimeUnit.MILLISECONDS)) {
|
||||
if (errorLatch.await(1000, TimeUnit.MILLISECONDS)) {
|
||||
fail("there was an error, check the console for thread or thread allocation failure");
|
||||
break;
|
||||
}
|
||||
}
|
||||
working = false;
|
||||
}
|
||||
|
||||
private void setupReceiver(final Connection connection) throws Exception {
|
||||
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final MessageConsumer consumer = session.createConsumer(requestDestination);
|
||||
final MessageProducer sender = session.createProducer(replyDestination);
|
||||
connection.start();
|
||||
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (working) {
|
||||
// wait for messages in infinitive loop
|
||||
// time out is set to show the client is awaiting
|
||||
try {
|
||||
TextMessage msg = (TextMessage) consumer.receive(20000);
|
||||
if (msg == null) {
|
||||
errorLatch.countDown();
|
||||
fail("Response timed out." + " latchCount=" + roundTripLatch.getCount());
|
||||
}
|
||||
else {
|
||||
String result = msg.getText();
|
||||
//System.out.println("Request:" + (i++)
|
||||
// + ", msg=" + result + ", ID" + msg.getJMSMessageID());
|
||||
TextMessage response = session.createTextMessage();
|
||||
response.setJMSCorrelationID(msg.getJMSMessageID());
|
||||
response.setText(result);
|
||||
sender.send(response);
|
||||
}
|
||||
}
|
||||
catch (JMSException e) {
|
||||
if (working) {
|
||||
errorLatch.countDown();
|
||||
fail("Unexpected exception:" + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
class MessageSenderReceiver implements Runnable {
|
||||
|
||||
Destination reqDest;
|
||||
Destination replyDest;
|
||||
String origMsg;
|
||||
|
||||
public MessageSenderReceiver(Destination reqDest, Destination replyDest, String msg) throws Exception {
|
||||
this.replyDest = replyDest;
|
||||
this.reqDest = reqDest;
|
||||
this.origMsg = msg;
|
||||
}
|
||||
|
||||
private int getIndexFromCurrentThread() {
|
||||
String name = Thread.currentThread().getName();
|
||||
String num = name.substring(name.lastIndexOf('-') + 1);
|
||||
int idx = Integer.parseInt(num) - 1;
|
||||
assertTrue("idx is in range: idx=" + idx, idx < NUM_THREADS);
|
||||
return idx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// get thread session and producer from pool
|
||||
int threadIndex = getIndexFromCurrentThread();
|
||||
Session session = sessions[threadIndex];
|
||||
MessageProducer producer = producers[threadIndex];
|
||||
|
||||
final Message sendJmsMsg = session.createTextMessage(origMsg);
|
||||
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
producer.send(sendJmsMsg);
|
||||
|
||||
String jmsId = sendJmsMsg.getJMSMessageID();
|
||||
String selector = "JMSCorrelationID='" + jmsId + "'";
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(replyDest, selector);
|
||||
Message receiveJmsMsg = consumer.receive(2000);
|
||||
consumer.close();
|
||||
if (receiveJmsMsg == null) {
|
||||
errorLatch.countDown();
|
||||
fail("Unable to receive response for:" + origMsg + ", with selector=" + selector);
|
||||
}
|
||||
else {
|
||||
//System.out.println("received response message :"
|
||||
// + ((TextMessage) receiveJmsMsg).getText()
|
||||
// + " with selector : " + selector);
|
||||
roundTripLatch.countDown();
|
||||
}
|
||||
}
|
||||
catch (JMSException e) {
|
||||
fail("unexpected exception:" + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LimitedThreadFactory implements ThreadFactory {
|
||||
|
||||
int threadCount;
|
||||
private ThreadFactory factory;
|
||||
|
||||
public LimitedThreadFactory(ThreadFactory threadFactory) {
|
||||
this.factory = threadFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable arg0) {
|
||||
if (++threadCount > NUM_THREADS) {
|
||||
errorLatch.countDown();
|
||||
fail("too many threads requested");
|
||||
}
|
||||
return factory.newThread(arg0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,320 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.QueueConnection;
|
||||
import javax.jms.QueueConnectionFactory;
|
||||
import javax.jms.QueueReceiver;
|
||||
import javax.jms.QueueSender;
|
||||
import javax.jms.QueueSession;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.AutoFailTestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.util.Wait;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* AMQ1936Test
|
||||
*/
|
||||
public class AMQ1936Test extends TestCase {
|
||||
|
||||
private final static Logger logger = Logger.getLogger(AMQ1936Test.class);
|
||||
private final static String TEST_QUEUE_NAME = "dynamicQueues/duplicate.message.test.queue";
|
||||
// //--
|
||||
//
|
||||
private final static long TEST_MESSAGE_COUNT = 6000; // The number of test messages to use
|
||||
//
|
||||
// //--
|
||||
private final static int CONSUMER_COUNT = 2; // The number of message receiver instances
|
||||
private final static boolean TRANSACTED_RECEIVE = true; // Flag used by receiver which indicates messages should be
|
||||
// processed within a JMS transaction
|
||||
|
||||
private final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(CONSUMER_COUNT, CONSUMER_COUNT, Long.MAX_VALUE, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
|
||||
private final ThreadedMessageReceiver[] receivers = new ThreadedMessageReceiver[CONSUMER_COUNT];
|
||||
private BrokerService broker = null;
|
||||
static QueueConnectionFactory connectionFactory = null;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
broker = new BrokerService();
|
||||
broker.getSystemUsage().getMemoryUsage().setLimit(5 * 1024 * 1024);
|
||||
broker.setBrokerName("test");
|
||||
broker.setDeleteAllMessagesOnStartup(true);
|
||||
broker.start();
|
||||
connectionFactory = new ActiveMQConnectionFactory("vm://test");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
if (threadPool != null) {
|
||||
// signal receivers to stop
|
||||
for (ThreadedMessageReceiver receiver : receivers) {
|
||||
receiver.setShouldStop(true);
|
||||
}
|
||||
|
||||
logger.info("Waiting for receivers to shutdown..");
|
||||
if (!threadPool.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||
logger.warn("Not all receivers completed shutdown.");
|
||||
}
|
||||
else {
|
||||
logger.info("All receivers shutdown successfully..");
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("Stoping the broker.");
|
||||
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendTextMessage(String queueName, int i) throws JMSException, NamingException {
|
||||
QueueConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://test");
|
||||
QueueConnection queueConnection = null;
|
||||
QueueSession session = null;
|
||||
QueueSender sender = null;
|
||||
Queue queue = null;
|
||||
TextMessage message = null;
|
||||
|
||||
try {
|
||||
|
||||
// Create the queue connection
|
||||
queueConnection = connectionFactory.createQueueConnection();
|
||||
|
||||
session = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
queue = session.createQueue(TEST_QUEUE_NAME);
|
||||
sender = session.createSender(queue);
|
||||
sender.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
|
||||
message = session.createTextMessage(String.valueOf(i));
|
||||
|
||||
// send the message
|
||||
sender.send(message);
|
||||
|
||||
if (session.getTransacted()) {
|
||||
session.commit();
|
||||
}
|
||||
if (i % 1000 == 0) {
|
||||
logger.info("Message successfully sent to : " + queue.getQueueName() + " messageid: " + message.getJMSMessageID() + " content:" + message.getText());
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (sender != null) {
|
||||
sender.close();
|
||||
}
|
||||
if (session != null) {
|
||||
session.close();
|
||||
}
|
||||
if (queueConnection != null) {
|
||||
queueConnection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testForDuplicateMessages() throws Exception {
|
||||
final ConcurrentHashMap<String, String> messages = new ConcurrentHashMap<>();
|
||||
final Object lock = new Object();
|
||||
final CountDownLatch duplicateSignal = new CountDownLatch(1);
|
||||
final AtomicInteger messageCount = new AtomicInteger(0);
|
||||
|
||||
// add 1/2 the number of our total messages
|
||||
for (int i = 0; i < TEST_MESSAGE_COUNT / 2; i++) {
|
||||
if (duplicateSignal.getCount() == 0) {
|
||||
fail("Duplicate message id detected");
|
||||
}
|
||||
sendTextMessage(TEST_QUEUE_NAME, i);
|
||||
}
|
||||
|
||||
// create a number of consumers to read of the messages and start them with a handler which simply stores the
|
||||
// message ids
|
||||
// in a Map and checks for a duplicate
|
||||
for (int i = 0; i < CONSUMER_COUNT; i++) {
|
||||
receivers[i] = new ThreadedMessageReceiver(TEST_QUEUE_NAME, new IMessageHandler() {
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message) throws Exception {
|
||||
synchronized (lock) {
|
||||
int current = messageCount.incrementAndGet();
|
||||
if (current % 1000 == 0) {
|
||||
logger.info("Received message:" + message.getJMSMessageID() + " with content: " + ((TextMessage) message).getText());
|
||||
}
|
||||
if (messages.containsKey(message.getJMSMessageID())) {
|
||||
duplicateSignal.countDown();
|
||||
logger.fatal("duplicate message id detected:" + message.getJMSMessageID());
|
||||
fail("Duplicate message id detected:" + message.getJMSMessageID());
|
||||
}
|
||||
else {
|
||||
messages.put(message.getJMSMessageID(), message.getJMSMessageID());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
threadPool.submit(receivers[i]);
|
||||
}
|
||||
|
||||
// starting adding the remaining messages
|
||||
for (int i = 0; i < TEST_MESSAGE_COUNT / 2; i++) {
|
||||
if (duplicateSignal.getCount() == 0) {
|
||||
fail("Duplicate message id detected");
|
||||
}
|
||||
sendTextMessage(TEST_QUEUE_NAME, i);
|
||||
}
|
||||
|
||||
logger.info("sent all " + TEST_MESSAGE_COUNT + " messages");
|
||||
|
||||
// allow some time for messages to be delivered to receivers.
|
||||
boolean ok = Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return TEST_MESSAGE_COUNT == messages.size();
|
||||
}
|
||||
}, TimeUnit.MINUTES.toMillis(7));
|
||||
if (!ok) {
|
||||
AutoFailTestSupport.dumpAllThreads("--STUCK?--");
|
||||
}
|
||||
assertEquals("Number of messages received does not match the number sent", TEST_MESSAGE_COUNT, messages.size());
|
||||
assertEquals(TEST_MESSAGE_COUNT, messageCount.get());
|
||||
}
|
||||
|
||||
private final static class ThreadedMessageReceiver implements Runnable {
|
||||
|
||||
private IMessageHandler handler = null;
|
||||
private final AtomicBoolean shouldStop = new AtomicBoolean(false);
|
||||
|
||||
public ThreadedMessageReceiver(String queueName, IMessageHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
QueueConnection queueConnection = null;
|
||||
QueueSession session = null;
|
||||
QueueReceiver receiver = null;
|
||||
Queue queue = null;
|
||||
Message message = null;
|
||||
try {
|
||||
try {
|
||||
|
||||
queueConnection = connectionFactory.createQueueConnection();
|
||||
// create a transacted session
|
||||
session = queueConnection.createQueueSession(TRANSACTED_RECEIVE, Session.AUTO_ACKNOWLEDGE);
|
||||
queue = session.createQueue(TEST_QUEUE_NAME);
|
||||
receiver = session.createReceiver(queue);
|
||||
|
||||
// start the connection
|
||||
queueConnection.start();
|
||||
|
||||
logger.info("Receiver " + Thread.currentThread().getName() + " connected.");
|
||||
|
||||
// start receive loop
|
||||
while (!(shouldStop.get() || Thread.currentThread().isInterrupted())) {
|
||||
try {
|
||||
message = receiver.receive(200);
|
||||
}
|
||||
catch (Exception e) {
|
||||
//
|
||||
// ignore interrupted exceptions
|
||||
//
|
||||
if (e instanceof InterruptedException || e.getCause() instanceof InterruptedException) {
|
||||
/* ignore */
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (message != null && this.handler != null) {
|
||||
this.handler.onMessage(message);
|
||||
}
|
||||
|
||||
// commit session on successful handling of message
|
||||
if (session.getTransacted()) {
|
||||
session.commit();
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Receiver " + Thread.currentThread().getName() + " shutting down.");
|
||||
|
||||
}
|
||||
finally {
|
||||
if (receiver != null) {
|
||||
try {
|
||||
receiver.close();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
logger.warn(e);
|
||||
}
|
||||
}
|
||||
if (session != null) {
|
||||
try {
|
||||
session.close();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
logger.warn(e);
|
||||
}
|
||||
}
|
||||
if (queueConnection != null) {
|
||||
queueConnection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JMSException e) {
|
||||
logger.error(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (NamingException e) {
|
||||
logger.error(e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void setShouldStop(Boolean shouldStop) {
|
||||
this.shouldStop.set(shouldStop);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IMessageHandler {
|
||||
|
||||
void onMessage(Message message) throws Exception;
|
||||
}
|
||||
}
|
|
@ -1,275 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ExceptionListener;
|
||||
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.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This is a test case for the issue reported at: https://issues.apache.org/activemq/browse/AMQ-2021 Bug is modification
|
||||
* of inflight message properties so the failure can manifest itself in a bunch or ways, from message receipt with null
|
||||
* properties to marshall errors
|
||||
*/
|
||||
public class AMQ2021Test implements ExceptionListener, UncaughtExceptionHandler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AMQ2021Test.class);
|
||||
BrokerService brokerService;
|
||||
ArrayList<Thread> threads = new ArrayList<>();
|
||||
Vector<Throwable> exceptions;
|
||||
|
||||
@Rule
|
||||
public TestName name = new TestName();
|
||||
|
||||
AMQ2021Test testCase;
|
||||
|
||||
private final String ACTIVEMQ_BROKER_BIND = "tcp://localhost:0";
|
||||
private String CONSUMER_BROKER_URL = "?jms.redeliveryPolicy.maximumRedeliveries=1&jms.redeliveryPolicy.initialRedeliveryDelay=0";
|
||||
private String PRODUCER_BROKER_URL;
|
||||
|
||||
private final int numMessages = 1000;
|
||||
private final int numConsumers = 2;
|
||||
private final int dlqMessages = numMessages / 2;
|
||||
|
||||
private CountDownLatch receivedLatch;
|
||||
private ActiveMQTopic destination;
|
||||
private CountDownLatch started;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Thread.setDefaultUncaughtExceptionHandler(this);
|
||||
testCase = this;
|
||||
|
||||
// Start an embedded broker up.
|
||||
brokerService = new BrokerService();
|
||||
brokerService.setDeleteAllMessagesOnStartup(true);
|
||||
brokerService.addConnector(ACTIVEMQ_BROKER_BIND);
|
||||
brokerService.start();
|
||||
destination = new ActiveMQTopic(name.getMethodName());
|
||||
exceptions = new Vector<>();
|
||||
|
||||
CONSUMER_BROKER_URL = brokerService.getTransportConnectors().get(0).getPublishableConnectString() + CONSUMER_BROKER_URL;
|
||||
PRODUCER_BROKER_URL = brokerService.getTransportConnectors().get(0).getPublishableConnectString();
|
||||
|
||||
receivedLatch = new CountDownLatch(numConsumers * (numMessages + dlqMessages));
|
||||
started = new CountDownLatch(1);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
for (Thread t : threads) {
|
||||
t.interrupt();
|
||||
t.join();
|
||||
}
|
||||
brokerService.stop();
|
||||
}
|
||||
|
||||
@Test(timeout = 240000)
|
||||
public void testConcurrentTopicResendToDLQ() throws Exception {
|
||||
|
||||
for (int i = 0; i < numConsumers; i++) {
|
||||
ConsumerThread c1 = new ConsumerThread("Consumer-" + i);
|
||||
threads.add(c1);
|
||||
c1.start();
|
||||
}
|
||||
|
||||
assertTrue(started.await(10, TimeUnit.SECONDS));
|
||||
|
||||
Thread producer = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
produce(numMessages);
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
};
|
||||
threads.add(producer);
|
||||
producer.start();
|
||||
|
||||
boolean allGood = receivedLatch.await(90, TimeUnit.SECONDS);
|
||||
for (Throwable t : exceptions) {
|
||||
log.error("failing test with first exception", t);
|
||||
fail("exception during test : " + t);
|
||||
}
|
||||
assertTrue("excepted messages received within time limit", allGood);
|
||||
|
||||
assertEquals(0, exceptions.size());
|
||||
|
||||
for (int i = 0; i < numConsumers; i++) {
|
||||
// last recovery sends message to deq so is not received again
|
||||
assertEquals(dlqMessages * 2, ((ConsumerThread) threads.get(i)).recoveries);
|
||||
assertEquals(numMessages + dlqMessages, ((ConsumerThread) threads.get(i)).counter);
|
||||
}
|
||||
|
||||
// half of the messages for each consumer should go to the dlq but duplicates will
|
||||
// be suppressed
|
||||
consumeFromDLQ(dlqMessages);
|
||||
|
||||
}
|
||||
|
||||
private void consumeFromDLQ(int messageCount) throws Exception {
|
||||
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(CONSUMER_BROKER_URL);
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer dlqConsumer = session.createConsumer(new ActiveMQQueue("ActiveMQ.DLQ"));
|
||||
int count = 0;
|
||||
for (int i = 0; i < messageCount; i++) {
|
||||
if (dlqConsumer.receive(1000) == null) {
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
assertEquals(messageCount, count);
|
||||
}
|
||||
|
||||
public void produce(int count) throws Exception {
|
||||
Connection connection = null;
|
||||
try {
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(PRODUCER_BROKER_URL);
|
||||
connection = factory.createConnection();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setTimeToLive(0);
|
||||
connection.start();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
int id = i + 1;
|
||||
TextMessage message = session.createTextMessage(name.getMethodName() + " Message " + id);
|
||||
message.setIntProperty("MsgNumber", id);
|
||||
producer.send(message);
|
||||
|
||||
if (id % 500 == 0) {
|
||||
log.info("sent " + id + ", ith " + message);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JMSException e) {
|
||||
log.error("unexpected ex on produce", e);
|
||||
exceptions.add(e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ConsumerThread extends Thread implements MessageListener {
|
||||
|
||||
public long counter = 0;
|
||||
public long recoveries = 0;
|
||||
private Session session;
|
||||
|
||||
public ConsumerThread(String threadId) {
|
||||
super(threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(CONSUMER_BROKER_URL);
|
||||
Connection connection = connectionFactory.createConnection();
|
||||
connection.setExceptionListener(testCase);
|
||||
connection.setClientID(getName());
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
MessageConsumer consumer = session.createDurableSubscriber(destination, getName());
|
||||
consumer.setMessageListener(this);
|
||||
connection.start();
|
||||
|
||||
started.countDown();
|
||||
|
||||
}
|
||||
catch (JMSException exception) {
|
||||
log.error("unexpected ex in consumer run", exception);
|
||||
exceptions.add(exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
try {
|
||||
counter++;
|
||||
int messageNumber = message.getIntProperty("MsgNumber");
|
||||
if (messageNumber % 2 == 0) {
|
||||
session.recover();
|
||||
recoveries++;
|
||||
}
|
||||
else {
|
||||
message.acknowledge();
|
||||
}
|
||||
|
||||
if (counter % 200 == 0) {
|
||||
log.info("recoveries:" + recoveries + ", Received " + counter + ", counter'th " + message);
|
||||
}
|
||||
receivedLatch.countDown();
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("unexpected ex on onMessage", e);
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(JMSException exception) {
|
||||
log.info("Unexpected JMSException", exception);
|
||||
exceptions.add(exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable exception) {
|
||||
log.info("Unexpected exception from thread " + thread + ", ex: " + exception);
|
||||
exceptions.add(exception);
|
||||
}
|
||||
}
|
|
@ -1,188 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.QueueConnection;
|
||||
import javax.jms.QueueConnectionFactory;
|
||||
import javax.jms.QueueReceiver;
|
||||
import javax.jms.QueueSession;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.jms.Topic;
|
||||
import javax.jms.TopicConnection;
|
||||
import javax.jms.TopicConnectionFactory;
|
||||
import javax.jms.TopicPublisher;
|
||||
import javax.jms.TopicSession;
|
||||
import javax.jms.TopicSubscriber;
|
||||
import javax.naming.InitialContext;
|
||||
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AMQ2084Test {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AMQ2084Test.class);
|
||||
BrokerService broker;
|
||||
CountDownLatch qreceived;
|
||||
String connectionUri;
|
||||
|
||||
@Before
|
||||
public void startBroker() throws Exception {
|
||||
broker = new BrokerService();
|
||||
broker.setPersistent(false);
|
||||
connectionUri = broker.addConnector("tcp://localhost:0").getPublishableConnectString();
|
||||
broker.start();
|
||||
|
||||
qreceived = new CountDownLatch(1);
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopBroker() throws Exception {
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public void listenQueue(final String queueName, final String selectors) {
|
||||
try {
|
||||
Properties props = new Properties();
|
||||
props.put("java.naming.factory.initial", "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
|
||||
props.put("java.naming.provider.url", connectionUri);
|
||||
props.put("queue.queueName", queueName);
|
||||
|
||||
javax.naming.Context ctx = new InitialContext(props);
|
||||
QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory");
|
||||
QueueConnection conn = factory.createQueueConnection();
|
||||
final Queue queue = (Queue) ctx.lookup("queueName");
|
||||
QueueSession session = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
QueueReceiver receiver = session.createReceiver(queue, selectors);
|
||||
System.out.println("Message Selector: " + receiver.getMessageSelector());
|
||||
receiver.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
try {
|
||||
if (message instanceof TextMessage) {
|
||||
TextMessage txtMsg = (TextMessage) message;
|
||||
String msg = txtMsg.getText();
|
||||
LOG.info("Queue Message Received: " + queueName + " - " + msg);
|
||||
qreceived.countDown();
|
||||
|
||||
}
|
||||
message.acknowledge();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
conn.start();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void listenTopic(final String topicName, final String selectors) {
|
||||
try {
|
||||
Properties props = new Properties();
|
||||
props.put("java.naming.factory.initial", "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
|
||||
props.put("java.naming.provider.url", connectionUri);
|
||||
props.put("topic.topicName", topicName);
|
||||
|
||||
javax.naming.Context ctx = new InitialContext(props);
|
||||
TopicConnectionFactory factory = (TopicConnectionFactory) ctx.lookup("ConnectionFactory");
|
||||
TopicConnection conn = factory.createTopicConnection();
|
||||
final Topic topic = (Topic) ctx.lookup("topicName");
|
||||
TopicSession session = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
TopicSubscriber receiver = session.createSubscriber(topic, selectors, false);
|
||||
|
||||
receiver.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
try {
|
||||
if (message instanceof TextMessage) {
|
||||
TextMessage txtMsg = (TextMessage) message;
|
||||
String msg = txtMsg.getText();
|
||||
LOG.info("Topic Message Received: " + topicName + " - " + msg);
|
||||
}
|
||||
message.acknowledge();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
conn.start();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void publish(String topicName, String message) {
|
||||
try {
|
||||
Properties props = new Properties();
|
||||
props.put("java.naming.factory.initial", "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
|
||||
props.put("java.naming.provider.url", connectionUri);
|
||||
props.put("topic.topicName", topicName);
|
||||
javax.naming.Context ctx = new InitialContext(props);
|
||||
TopicConnectionFactory factory = (TopicConnectionFactory) ctx.lookup("ConnectionFactory");
|
||||
TopicConnection conn = factory.createTopicConnection();
|
||||
Topic topic = (Topic) ctx.lookup("topicName");
|
||||
TopicSession session = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
TopicPublisher publisher = session.createPublisher(topic);
|
||||
if (message != null) {
|
||||
Message msg = session.createTextMessage(message);
|
||||
publisher.send(msg);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tryXpathSelectorMatch() throws Exception {
|
||||
String xPath = "XPATH '//books//book[@lang=''en'']'";
|
||||
listenQueue("Consumer.Sample.VirtualTopic.TestXpath", xPath);
|
||||
publish("VirtualTopic.TestXpath", "<?xml version=\"1.0\" encoding=\"UTF-8\"?><books><book lang=\"en\">ABC</book></books>");
|
||||
assertTrue("topic received: ", qreceived.await(20, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tryXpathSelectorNoMatch() throws Exception {
|
||||
String xPath = "XPATH '//books//book[@lang=''es'']'";
|
||||
listenQueue("Consumer.Sample.VirtualTopic.TestXpath", xPath);
|
||||
publish("VirtualTopic.TestXpath", "<?xml version=\"1.0\" encoding=\"UTF-8\"?><books><book lang=\"en\">ABC</book></books>");
|
||||
assertFalse("topic did not receive unmatched", qreceived.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerTestSupport;
|
||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.apache.activemq.command.ActiveMQMapMessage;
|
||||
import org.apache.activemq.command.ActiveMQObjectMessage;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTextMessage;
|
||||
import org.apache.activemq.usecases.MyObject;
|
||||
|
||||
public class AMQ2103Test extends BrokerTestSupport {
|
||||
|
||||
static PolicyEntry reduceMemoryFootprint = new PolicyEntry();
|
||||
|
||||
static {
|
||||
reduceMemoryFootprint.setReduceMemoryFootprint(true);
|
||||
}
|
||||
|
||||
public PolicyEntry defaultPolicy = reduceMemoryFootprint;
|
||||
|
||||
@Override
|
||||
protected PolicyEntry getDefaultPolicy() {
|
||||
return defaultPolicy;
|
||||
}
|
||||
|
||||
public void initCombosForTestVerifyMarshalledStateIsCleared() throws Exception {
|
||||
addCombinationValues("defaultPolicy", new Object[]{defaultPolicy, null});
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return suite(AMQ2103Test.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* use mem persistence so no marshaling,
|
||||
* reduceMemoryFootprint on/off that will reduce memory by whacking the marshaled state
|
||||
* With vm transport and deferred serialisation and no persistence (mem persistence),
|
||||
* we see the message as sent by the client so we can validate the contents against
|
||||
* the policy
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testVerifyMarshalledStateIsCleared() throws Exception {
|
||||
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost");
|
||||
factory.setOptimizedMessageDispatch(true);
|
||||
factory.setObjectMessageSerializationDefered(true);
|
||||
factory.setCopyMessageOnSend(false);
|
||||
|
||||
Connection connection = factory.createConnection();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
ActiveMQDestination destination = new ActiveMQQueue("testQ");
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
connection.start();
|
||||
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
final MyObject obj = new MyObject("A message");
|
||||
ActiveMQObjectMessage m1 = (ActiveMQObjectMessage) session.createObjectMessage();
|
||||
m1.setObject(obj);
|
||||
producer.send(m1);
|
||||
|
||||
ActiveMQTextMessage m2 = new ActiveMQTextMessage();
|
||||
m2.setText("Test Message Payload.");
|
||||
producer.send(m2);
|
||||
|
||||
ActiveMQMapMessage m3 = new ActiveMQMapMessage();
|
||||
m3.setString("text", "my message");
|
||||
producer.send(m3);
|
||||
|
||||
Message m = consumer.receive(maxWait);
|
||||
assertNotNull(m);
|
||||
assertEquals(m1.getMessageId().toString(), m.getJMSMessageID());
|
||||
assertTrue(m instanceof ActiveMQObjectMessage);
|
||||
|
||||
if (getDefaultPolicy() != null) {
|
||||
assertNull("object data cleared by reduceMemoryFootprint (and never marshalled as using mem persistence)", ((ActiveMQObjectMessage) m).getObject());
|
||||
}
|
||||
|
||||
// verify no serialisation via vm transport
|
||||
assertEquals("writeObject called", 0, obj.getWriteObjectCalled());
|
||||
assertEquals("readObject called", 0, obj.getReadObjectCalled());
|
||||
assertEquals("readObjectNoData called", 0, obj.getReadObjectNoDataCalled());
|
||||
|
||||
m = consumer.receive(maxWait);
|
||||
assertNotNull(m);
|
||||
assertEquals(m2.getMessageId().toString(), m.getJMSMessageID());
|
||||
assertTrue(m instanceof ActiveMQTextMessage);
|
||||
|
||||
if (getDefaultPolicy() != null) {
|
||||
assertNull("text cleared by reduceMemoryFootprint (and never marshalled as using mem persistence)", ((ActiveMQTextMessage) m).getText());
|
||||
}
|
||||
|
||||
m = consumer.receive(maxWait);
|
||||
assertNotNull(m);
|
||||
assertEquals(m3.getMessageId().toString(), m.getJMSMessageID());
|
||||
assertTrue(m instanceof ActiveMQMapMessage);
|
||||
|
||||
if (getDefaultPolicy() != null) {
|
||||
assertNull("text cleared by reduceMemoryFootprint (and never marshalled as using mem persistence)", ((ActiveMQMapMessage) m).getStringProperty("text"));
|
||||
}
|
||||
|
||||
connection.close();
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.leveldb.LevelDBStore;
|
||||
|
||||
public class AMQ2149LevelDBTest extends AMQ2149Test {
|
||||
|
||||
@Override
|
||||
protected void configurePersistenceAdapter(BrokerService brokerService) throws Exception {
|
||||
LevelDBStore persistenceFactory = new LevelDBStore();
|
||||
persistenceFactory.setDirectory(dataDirFile);
|
||||
brokerService.setPersistenceAdapter(persistenceFactory);
|
||||
}
|
||||
}
|
|
@ -1,614 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.IllegalStateException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.jms.*;
|
||||
|
||||
import org.apache.activemq.AutoFailTestSupport;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.region.Destination;
|
||||
import org.apache.activemq.broker.region.DestinationStatistics;
|
||||
import org.apache.activemq.broker.region.RegionBroker;
|
||||
import org.apache.activemq.broker.util.LoggingBrokerPlugin;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.junit.rules.TestName;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
interface Configurer {
|
||||
|
||||
public void configure(BrokerService broker) throws Exception;
|
||||
}
|
||||
|
||||
public class AMQ2149Test {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AMQ2149Test.class);
|
||||
@Rule
|
||||
public TestName testName = new TestName();
|
||||
|
||||
private static final String BROKER_CONNECTOR = "tcp://localhost:61617";
|
||||
private static final String DEFAULT_BROKER_URL = "failover:(" + BROKER_CONNECTOR + ")?maxReconnectDelay=1000&useExponentialBackOff=false";
|
||||
|
||||
private final String SEQ_NUM_PROPERTY = "seqNum";
|
||||
|
||||
final int MESSAGE_LENGTH_BYTES = 75 * 1024;
|
||||
final long SLEEP_BETWEEN_SEND_MS = 25;
|
||||
final int NUM_SENDERS_AND_RECEIVERS = 10;
|
||||
final Object brokerLock = new Object();
|
||||
|
||||
private static final long DEFAULT_BROKER_STOP_PERIOD = 10 * 1000;
|
||||
private static final long DEFAULT_NUM_TO_SEND = 1400;
|
||||
|
||||
long brokerStopPeriod = DEFAULT_BROKER_STOP_PERIOD;
|
||||
long numtoSend = DEFAULT_NUM_TO_SEND;
|
||||
long sleepBetweenSend = SLEEP_BETWEEN_SEND_MS;
|
||||
String brokerURL = DEFAULT_BROKER_URL;
|
||||
|
||||
int numBrokerRestarts = 0;
|
||||
final static int MAX_BROKER_RESTARTS = 4;
|
||||
BrokerService broker;
|
||||
Vector<Throwable> exceptions = new Vector<>();
|
||||
|
||||
protected File dataDirFile;
|
||||
final LoggingBrokerPlugin[] plugins = new LoggingBrokerPlugin[]{new LoggingBrokerPlugin()};
|
||||
|
||||
public void createBroker(Configurer configurer) throws Exception {
|
||||
broker = new BrokerService();
|
||||
configurePersistenceAdapter(broker);
|
||||
|
||||
broker.getSystemUsage().getMemoryUsage().setLimit(MESSAGE_LENGTH_BYTES * 200 * NUM_SENDERS_AND_RECEIVERS);
|
||||
|
||||
broker.addConnector(BROKER_CONNECTOR);
|
||||
broker.setBrokerName(testName.getMethodName());
|
||||
broker.setDataDirectoryFile(dataDirFile);
|
||||
if (configurer != null) {
|
||||
configurer.configure(broker);
|
||||
}
|
||||
broker.start();
|
||||
}
|
||||
|
||||
protected void configurePersistenceAdapter(BrokerService brokerService) throws Exception {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
LOG.debug("Starting test {}", testName.getMethodName());
|
||||
dataDirFile = new File("target/" + testName.getMethodName());
|
||||
numtoSend = DEFAULT_NUM_TO_SEND;
|
||||
brokerStopPeriod = DEFAULT_BROKER_STOP_PERIOD;
|
||||
sleepBetweenSend = SLEEP_BETWEEN_SEND_MS;
|
||||
brokerURL = DEFAULT_BROKER_URL;
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
Future<Boolean> future = executor.submit(new TeardownTask(brokerLock, broker));
|
||||
try {
|
||||
LOG.debug("Teardown started.");
|
||||
long start = System.currentTimeMillis();
|
||||
Boolean result = future.get(30, TimeUnit.SECONDS);
|
||||
long finish = System.currentTimeMillis();
|
||||
LOG.debug("Result of teardown: {} after {} ms ", result, (finish - start));
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
fail("Teardown timed out");
|
||||
AutoFailTestSupport.dumpAllThreads(testName.getMethodName());
|
||||
}
|
||||
executor.shutdownNow();
|
||||
exceptions.clear();
|
||||
}
|
||||
|
||||
private String buildLongString() {
|
||||
final StringBuilder stringBuilder = new StringBuilder(MESSAGE_LENGTH_BYTES);
|
||||
for (int i = 0; i < MESSAGE_LENGTH_BYTES; ++i) {
|
||||
stringBuilder.append((int) (Math.random() * 10));
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
HashSet<Connection> connections = new HashSet<>();
|
||||
|
||||
private class Receiver implements MessageListener {
|
||||
|
||||
private final javax.jms.Destination dest;
|
||||
|
||||
private final Connection connection;
|
||||
|
||||
private final Session session;
|
||||
|
||||
private final MessageConsumer messageConsumer;
|
||||
|
||||
private AtomicLong nextExpectedSeqNum = new AtomicLong();
|
||||
|
||||
private final boolean transactional;
|
||||
|
||||
private String lastId = null;
|
||||
|
||||
public Receiver(javax.jms.Destination dest, boolean transactional) throws JMSException {
|
||||
this.dest = dest;
|
||||
this.transactional = transactional;
|
||||
connection = new ActiveMQConnectionFactory(brokerURL).createConnection();
|
||||
connection.setClientID(dest.toString());
|
||||
session = connection.createSession(transactional, transactional ? Session.SESSION_TRANSACTED : Session.AUTO_ACKNOWLEDGE);
|
||||
if (ActiveMQDestination.transform(dest).isTopic()) {
|
||||
messageConsumer = session.createDurableSubscriber((Topic) dest, dest.toString());
|
||||
}
|
||||
else {
|
||||
messageConsumer = session.createConsumer(dest);
|
||||
}
|
||||
messageConsumer.setMessageListener(this);
|
||||
connection.start();
|
||||
connections.add(connection);
|
||||
}
|
||||
|
||||
public void close() throws JMSException {
|
||||
connection.close();
|
||||
}
|
||||
|
||||
public long getNextExpectedSeqNo() {
|
||||
return nextExpectedSeqNum.get();
|
||||
}
|
||||
|
||||
final int TRANSACITON_BATCH = 500;
|
||||
boolean resumeOnNextOrPreviousIsOk = false;
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
try {
|
||||
final long seqNum = message.getLongProperty(SEQ_NUM_PROPERTY);
|
||||
if ((seqNum % TRANSACITON_BATCH) == 0) {
|
||||
LOG.info(dest + " received " + seqNum);
|
||||
|
||||
if (transactional) {
|
||||
LOG.info("committing..");
|
||||
session.commit();
|
||||
}
|
||||
}
|
||||
if (resumeOnNextOrPreviousIsOk) {
|
||||
// after an indoubt commit we need to accept what we get (within reason)
|
||||
if (seqNum != nextExpectedSeqNum.get()) {
|
||||
final long l = nextExpectedSeqNum.get();
|
||||
if (seqNum == l - (TRANSACITON_BATCH - 1)) {
|
||||
nextExpectedSeqNum.compareAndSet(l, l - (TRANSACITON_BATCH - 1));
|
||||
LOG.info("In doubt commit failed, getting replay at:" + nextExpectedSeqNum);
|
||||
}
|
||||
}
|
||||
resumeOnNextOrPreviousIsOk = false;
|
||||
}
|
||||
if (seqNum != nextExpectedSeqNum.get()) {
|
||||
LOG.warn(dest + " received " + seqNum + " in msg: " + message.getJMSMessageID() + " expected " + nextExpectedSeqNum + ", lastId: " + lastId + ", message:" + message);
|
||||
fail(dest + " received " + seqNum + " expected " + nextExpectedSeqNum);
|
||||
}
|
||||
nextExpectedSeqNum.incrementAndGet();
|
||||
lastId = message.getJMSMessageID();
|
||||
}
|
||||
catch (TransactionRolledBackException expectedSometimesOnFailoverRecovery) {
|
||||
LOG.info("got rollback: " + expectedSometimesOnFailoverRecovery);
|
||||
if (expectedSometimesOnFailoverRecovery.getMessage().contains("completion in doubt")) {
|
||||
// in doubt - either commit command or reply missing
|
||||
// don't know if we will get a replay
|
||||
resumeOnNextOrPreviousIsOk = true;
|
||||
nextExpectedSeqNum.incrementAndGet();
|
||||
LOG.info("in doubt transaction completion: ok to get next or previous batch. next:" + nextExpectedSeqNum);
|
||||
}
|
||||
else {
|
||||
resumeOnNextOrPreviousIsOk = false;
|
||||
// batch will be replayed
|
||||
nextExpectedSeqNum.addAndGet(-(TRANSACITON_BATCH - 1));
|
||||
}
|
||||
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(dest + " onMessage error", e);
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class Sender implements Runnable {
|
||||
|
||||
private final javax.jms.Destination dest;
|
||||
|
||||
private final Connection connection;
|
||||
|
||||
private final Session session;
|
||||
|
||||
private final MessageProducer messageProducer;
|
||||
|
||||
private volatile long nextSequenceNumber = 0;
|
||||
private final Object guard = new Object();
|
||||
|
||||
public Sender(javax.jms.Destination dest) throws JMSException {
|
||||
this.dest = dest;
|
||||
connection = new ActiveMQConnectionFactory(brokerURL).createConnection();
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
messageProducer = session.createProducer(dest);
|
||||
messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
connection.start();
|
||||
connections.add(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
final String longString = buildLongString();
|
||||
long nextSequenceNumber = this.nextSequenceNumber;
|
||||
while (nextSequenceNumber < numtoSend) {
|
||||
try {
|
||||
final Message message = session.createTextMessage(longString);
|
||||
message.setLongProperty(SEQ_NUM_PROPERTY, nextSequenceNumber);
|
||||
synchronized (guard) {
|
||||
if (nextSequenceNumber == this.nextSequenceNumber) {
|
||||
this.nextSequenceNumber = nextSequenceNumber + 1;
|
||||
messageProducer.send(message);
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((nextSequenceNumber % 500) == 0) {
|
||||
LOG.info(dest + " sent " + nextSequenceNumber);
|
||||
}
|
||||
|
||||
}
|
||||
catch (javax.jms.IllegalStateException e) {
|
||||
LOG.error(dest + " bailing on send error", e);
|
||||
exceptions.add(e);
|
||||
break;
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(dest + " send error", e);
|
||||
exceptions.add(e);
|
||||
}
|
||||
if (sleepBetweenSend > 0) {
|
||||
try {
|
||||
Thread.sleep(sleepBetweenSend);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
LOG.warn(dest + " sleep interrupted", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
connection.close();
|
||||
}
|
||||
catch (JMSException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// attempt to simply replicate leveldb failure. no joy yet
|
||||
public void x_testRestartReReceive() throws Exception {
|
||||
createBroker(new Configurer() {
|
||||
@Override
|
||||
public void configure(BrokerService broker) throws Exception {
|
||||
broker.deleteAllMessages();
|
||||
}
|
||||
});
|
||||
|
||||
final javax.jms.Destination destination = ActiveMQDestination.createDestination("test.dest.X", ActiveMQDestination.QUEUE_TYPE);
|
||||
Thread thread = new Thread(new Sender(destination));
|
||||
thread.start();
|
||||
thread.join();
|
||||
|
||||
Connection connection = new ActiveMQConnectionFactory(brokerURL).createConnection();
|
||||
connection.setClientID(destination.toString());
|
||||
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
MessageConsumer messageConsumer = session.createConsumer(destination);
|
||||
connection.start();
|
||||
|
||||
int batch = 200;
|
||||
long expectedSeq;
|
||||
|
||||
final TimerTask restartTask = scheduleRestartTask(null, new Configurer() {
|
||||
@Override
|
||||
public void configure(BrokerService broker) throws Exception {
|
||||
}
|
||||
});
|
||||
|
||||
expectedSeq = 0;
|
||||
for (int s = 0; s < 4; s++) {
|
||||
for (int i = 0; i < batch; i++) {
|
||||
Message message = messageConsumer.receive(20000);
|
||||
assertNotNull("s:" + s + ", i:" + i, message);
|
||||
final long seqNum = message.getLongProperty(SEQ_NUM_PROPERTY);
|
||||
assertEquals("expected order s:" + s, expectedSeq++, seqNum);
|
||||
|
||||
if (i > 0 && i % 600 == 0) {
|
||||
LOG.info("Commit on %5");
|
||||
// session.commit();
|
||||
}
|
||||
}
|
||||
restartTask.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// no need to run this unless there are some issues with the others
|
||||
public void vanilaVerify_testOrder() throws Exception {
|
||||
|
||||
createBroker(new Configurer() {
|
||||
@Override
|
||||
public void configure(BrokerService broker) throws Exception {
|
||||
broker.deleteAllMessages();
|
||||
}
|
||||
});
|
||||
|
||||
verifyOrderedMessageReceipt();
|
||||
verifyStats(false);
|
||||
}
|
||||
|
||||
@Test(timeout = 5 * 60 * 1000)
|
||||
public void testOrderWithRestart() throws Exception {
|
||||
createBroker(new Configurer() {
|
||||
@Override
|
||||
public void configure(BrokerService broker) throws Exception {
|
||||
broker.deleteAllMessages();
|
||||
}
|
||||
});
|
||||
|
||||
final Timer timer = new Timer();
|
||||
scheduleRestartTask(timer, new Configurer() {
|
||||
@Override
|
||||
public void configure(BrokerService broker) throws Exception {
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
verifyOrderedMessageReceipt();
|
||||
}
|
||||
finally {
|
||||
timer.cancel();
|
||||
}
|
||||
|
||||
verifyStats(true);
|
||||
}
|
||||
|
||||
@Test(timeout = 5 * 60 * 1000)
|
||||
public void testTopicOrderWithRestart() throws Exception {
|
||||
createBroker(new Configurer() {
|
||||
@Override
|
||||
public void configure(BrokerService broker) throws Exception {
|
||||
broker.deleteAllMessages();
|
||||
}
|
||||
});
|
||||
|
||||
final Timer timer = new Timer();
|
||||
scheduleRestartTask(timer, null);
|
||||
|
||||
try {
|
||||
verifyOrderedMessageReceipt(ActiveMQDestination.TOPIC_TYPE);
|
||||
}
|
||||
finally {
|
||||
timer.cancel();
|
||||
}
|
||||
|
||||
verifyStats(true);
|
||||
}
|
||||
|
||||
@Test(timeout = 5 * 60 * 1000)
|
||||
public void testQueueTransactionalOrderWithRestart() throws Exception {
|
||||
doTestTransactionalOrderWithRestart(ActiveMQDestination.QUEUE_TYPE);
|
||||
}
|
||||
|
||||
@Test(timeout = 5 * 60 * 1000)
|
||||
public void testTopicTransactionalOrderWithRestart() throws Exception {
|
||||
doTestTransactionalOrderWithRestart(ActiveMQDestination.TOPIC_TYPE);
|
||||
}
|
||||
|
||||
public void doTestTransactionalOrderWithRestart(byte destinationType) throws Exception {
|
||||
numtoSend = 10000;
|
||||
sleepBetweenSend = 3;
|
||||
brokerStopPeriod = 10 * 1000;
|
||||
|
||||
createBroker(new Configurer() {
|
||||
@Override
|
||||
public void configure(BrokerService broker) throws Exception {
|
||||
broker.deleteAllMessages();
|
||||
}
|
||||
});
|
||||
|
||||
final Timer timer = new Timer();
|
||||
scheduleRestartTask(timer, null);
|
||||
|
||||
try {
|
||||
verifyOrderedMessageReceipt(destinationType, 1, true);
|
||||
}
|
||||
finally {
|
||||
timer.cancel();
|
||||
}
|
||||
|
||||
verifyStats(true);
|
||||
}
|
||||
|
||||
private void verifyStats(boolean brokerRestarts) throws Exception {
|
||||
RegionBroker regionBroker = (RegionBroker) broker.getRegionBroker();
|
||||
|
||||
for (Destination dest : regionBroker.getQueueRegion().getDestinationMap().values()) {
|
||||
DestinationStatistics stats = dest.getDestinationStatistics();
|
||||
if (brokerRestarts) {
|
||||
// all bets are off w.r.t stats as there may be duplicate sends and duplicate
|
||||
// dispatches, all of which will be suppressed - either by the reference store
|
||||
// not allowing duplicate references or consumers acking duplicates
|
||||
LOG.info("with restart: not asserting qneue/dequeue stat match for: " + dest.getName() + " " + stats.getEnqueues().getCount() + " <= " + stats.getDequeues().getCount());
|
||||
}
|
||||
else {
|
||||
assertEquals("qneue/dequeue match for: " + dest.getName(), stats.getEnqueues().getCount(), stats.getDequeues().getCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TimerTask scheduleRestartTask(final Timer timer, final Configurer configurer) {
|
||||
class RestartTask extends TimerTask {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (brokerLock) {
|
||||
LOG.info("stopping broker..");
|
||||
try {
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("ex on broker stop", e);
|
||||
exceptions.add(e);
|
||||
}
|
||||
LOG.info("restarting broker");
|
||||
try {
|
||||
createBroker(configurer);
|
||||
broker.waitUntilStarted();
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("ex on broker restart", e);
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
if (++numBrokerRestarts < MAX_BROKER_RESTARTS && timer != null) {
|
||||
// do it again
|
||||
try {
|
||||
timer.schedule(new RestartTask(), brokerStopPeriod);
|
||||
}
|
||||
catch (IllegalStateException ignore_alreadyCancelled) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG.info("no longer stopping broker on reaching Max restarts: " + MAX_BROKER_RESTARTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
RestartTask task = new RestartTask();
|
||||
if (timer != null) {
|
||||
timer.schedule(task, brokerStopPeriod);
|
||||
}
|
||||
return task;
|
||||
}
|
||||
|
||||
private void verifyOrderedMessageReceipt(byte destinationType) throws Exception {
|
||||
verifyOrderedMessageReceipt(destinationType, NUM_SENDERS_AND_RECEIVERS, false);
|
||||
}
|
||||
|
||||
private void verifyOrderedMessageReceipt() throws Exception {
|
||||
verifyOrderedMessageReceipt(ActiveMQDestination.QUEUE_TYPE, NUM_SENDERS_AND_RECEIVERS, false);
|
||||
}
|
||||
|
||||
private void verifyOrderedMessageReceipt(byte destinationType,
|
||||
int concurrentPairs,
|
||||
boolean transactional) throws Exception {
|
||||
|
||||
Vector<Thread> threads = new Vector<>();
|
||||
Vector<Receiver> receivers = new Vector<>();
|
||||
|
||||
for (int i = 0; i < concurrentPairs; ++i) {
|
||||
final javax.jms.Destination destination = ActiveMQDestination.createDestination("test.dest." + i, destinationType);
|
||||
receivers.add(new Receiver(destination, transactional));
|
||||
Thread thread = new Thread(new Sender(destination));
|
||||
thread.start();
|
||||
threads.add(thread);
|
||||
}
|
||||
|
||||
final long expiry = System.currentTimeMillis() + 1000 * 60 * 4;
|
||||
while (!threads.isEmpty() && exceptions.isEmpty() && System.currentTimeMillis() < expiry) {
|
||||
Thread sendThread = threads.firstElement();
|
||||
sendThread.join(1000 * 30);
|
||||
if (!sendThread.isAlive()) {
|
||||
threads.remove(sendThread);
|
||||
}
|
||||
else {
|
||||
AutoFailTestSupport.dumpAllThreads("Send blocked");
|
||||
}
|
||||
}
|
||||
LOG.info("senders done..." + threads);
|
||||
|
||||
while (!receivers.isEmpty() && System.currentTimeMillis() < expiry) {
|
||||
Receiver receiver = receivers.firstElement();
|
||||
if (receiver.getNextExpectedSeqNo() >= numtoSend || !exceptions.isEmpty()) {
|
||||
receiver.close();
|
||||
receivers.remove(receiver);
|
||||
}
|
||||
}
|
||||
|
||||
for (Connection connection : connections) {
|
||||
try {
|
||||
connection.close();
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
connections.clear();
|
||||
|
||||
assertTrue("No timeout waiting for senders/receivers to complete", System.currentTimeMillis() < expiry);
|
||||
if (!exceptions.isEmpty()) {
|
||||
exceptions.get(0).printStackTrace();
|
||||
}
|
||||
|
||||
LOG.info("Dangling threads: " + threads);
|
||||
for (Thread dangling : threads) {
|
||||
dangling.interrupt();
|
||||
dangling.join(10 * 1000);
|
||||
}
|
||||
|
||||
assertTrue("No exceptions", exceptions.isEmpty());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TeardownTask implements Callable<Boolean> {
|
||||
|
||||
private final Object brokerLock;
|
||||
private BrokerService broker;
|
||||
|
||||
public TeardownTask(Object brokerLock, BrokerService broker) {
|
||||
this.brokerLock = brokerLock;
|
||||
this.broker = broker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean call() throws Exception {
|
||||
synchronized (brokerLock) {
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
}
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import javax.jms.*;
|
||||
import javax.jms.Queue;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class AMQ2171Test implements Thread.UncaughtExceptionHandler {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AMQ2171Test.class);
|
||||
private static final String BROKER_URL = "tcp://localhost:0";
|
||||
private static final int QUEUE_SIZE = 100;
|
||||
|
||||
private static BrokerService brokerService;
|
||||
private static Queue destination;
|
||||
|
||||
private String brokerUri;
|
||||
private String brokerUriNoPrefetch;
|
||||
private Collection<Throwable> exceptions = new CopyOnWriteArrayList<>();
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// Start an embedded broker up.
|
||||
brokerService = new BrokerService();
|
||||
brokerService.setDeleteAllMessagesOnStartup(true);
|
||||
brokerService.addConnector(BROKER_URL);
|
||||
brokerService.start();
|
||||
|
||||
brokerUri = brokerService.getTransportConnectors().get(0).getPublishableConnectString().toString();
|
||||
brokerUriNoPrefetch = brokerUri + "?jms.prefetchPolicy.all=0";
|
||||
|
||||
destination = new ActiveMQQueue("Test");
|
||||
produce(brokerUri, QUEUE_SIZE);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void addHandler() {
|
||||
Thread.setDefaultUncaughtExceptionHandler(this);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
brokerService.stop();
|
||||
}
|
||||
|
||||
@Test(timeout = 10000)
|
||||
public void testBrowsePrefetch() throws Exception {
|
||||
runTest(brokerUri);
|
||||
}
|
||||
|
||||
@Test(timeout = 10000)
|
||||
public void testBrowseNoPrefetch() throws Exception {
|
||||
runTest(brokerUriNoPrefetch);
|
||||
}
|
||||
|
||||
private void runTest(String brokerURL) throws Exception {
|
||||
|
||||
Connection connection = new ActiveMQConnectionFactory(brokerURL).createConnection();
|
||||
|
||||
try {
|
||||
connection.start();
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Enumeration<Message> unread = session.createBrowser(destination).getEnumeration();
|
||||
|
||||
int count = 0;
|
||||
while (unread.hasMoreElements()) {
|
||||
unread.nextElement();
|
||||
count++;
|
||||
}
|
||||
|
||||
assertEquals(QUEUE_SIZE, count);
|
||||
assertTrue(exceptions.isEmpty());
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
connection.close();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void produce(String brokerURL, int count) throws Exception {
|
||||
Connection connection = null;
|
||||
|
||||
try {
|
||||
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL);
|
||||
connection = factory.createConnection();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setTimeToLive(0);
|
||||
connection.start();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
int id = i + 1;
|
||||
TextMessage message = session.createTextMessage("Message " + id);
|
||||
message.setIntProperty("MsgNumber", id);
|
||||
producer.send(message);
|
||||
|
||||
if (id % 500 == 0) {
|
||||
LOG.info("sent " + id + ", ith " + message);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.Topic;
|
||||
import javax.jms.TopicConnection;
|
||||
import javax.jms.TopicSession;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.jmx.TopicSubscriptionViewMBean;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AMQ2200Test {
|
||||
|
||||
private static final String bindAddress = "tcp://0.0.0.0:0";
|
||||
private BrokerService broker;
|
||||
private ActiveMQConnectionFactory cf;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
broker = new BrokerService();
|
||||
broker.setDataDirectory("target" + File.separator + "activemq-data");
|
||||
broker.setPersistent(true);
|
||||
broker.setUseJmx(true);
|
||||
broker.setAdvisorySupport(false);
|
||||
broker.setDeleteAllMessagesOnStartup(true);
|
||||
broker.addConnector(bindAddress);
|
||||
String address = broker.getTransportConnectors().get(0).getPublishableConnectString();
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
|
||||
cf = new ActiveMQConnectionFactory(address);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTopicSubscriptionView() throws Exception {
|
||||
TopicConnection connection = cf.createTopicConnection();
|
||||
TopicSession session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
Topic destination = session.createTopic("TopicViewTestTopic");
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
assertNotNull(consumer);
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
|
||||
ObjectName subscriptionNames[] = broker.getAdminView().getTopicSubscribers();
|
||||
assertTrue(subscriptionNames.length > 0);
|
||||
|
||||
boolean fail = true;
|
||||
for (ObjectName name : subscriptionNames) {
|
||||
if (name.toString().contains("TopicViewTestTopic")) {
|
||||
TopicSubscriptionViewMBean sub = (TopicSubscriptionViewMBean) broker.getManagementContext().newProxyInstance(name, TopicSubscriptionViewMBean.class, true);
|
||||
assertNotNull(sub);
|
||||
assertTrue(sub.getSessionId() != -1);
|
||||
// Check that its the default value then configure something new.
|
||||
assertTrue(sub.getMaximumPendingQueueSize() == -1);
|
||||
sub.setMaximumPendingQueueSize(1000);
|
||||
assertTrue(sub.getMaximumPendingQueueSize() != -1);
|
||||
fail = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fail) {
|
||||
fail("Didn't find the TopicSubscriptionView");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.QueueConnection;
|
||||
import javax.jms.QueueSession;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TopicConnection;
|
||||
import javax.jms.TopicSession;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AMQ2213Test {
|
||||
|
||||
BrokerService broker;
|
||||
ConnectionFactory factory;
|
||||
Connection connection;
|
||||
Session session;
|
||||
Queue queue;
|
||||
MessageConsumer consumer;
|
||||
|
||||
public void createBroker(boolean deleteAll) throws Exception {
|
||||
broker = new BrokerService();
|
||||
broker.setDeleteAllMessagesOnStartup(deleteAll);
|
||||
broker.setDataDirectory("target/AMQ3145Test");
|
||||
broker.setUseJmx(true);
|
||||
broker.getManagementContext().setCreateConnector(false);
|
||||
broker.addConnector("tcp://localhost:0");
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
factory = new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getConnectUri().toString());
|
||||
connection = factory.createConnection();
|
||||
connection.start();
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void createBroker() throws Exception {
|
||||
createBroker(true);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (consumer != null) {
|
||||
consumer.close();
|
||||
}
|
||||
session.close();
|
||||
connection.stop();
|
||||
connection.close();
|
||||
broker.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsGenericSession() throws JMSException {
|
||||
assertNotNull(this.connection);
|
||||
Session sess = this.connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
assertTrue(sess.equals(sess));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsTopicSession() throws JMSException {
|
||||
assertNotNull(this.connection);
|
||||
assertTrue(this.connection instanceof TopicConnection);
|
||||
TopicSession sess = ((TopicConnection) this.connection).createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
assertTrue(sess.equals(sess));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsQueueSession() throws JMSException {
|
||||
assertNotNull(this.connection);
|
||||
assertTrue(this.connection instanceof QueueConnection);
|
||||
QueueSession sess = ((QueueConnection) this.connection).createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
assertTrue(sess.equals(sess));
|
||||
}
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.ActiveMQPrefetchPolicy;
|
||||
import org.apache.activemq.CombinationTestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.util.Wait;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AMQ2314Test extends CombinationTestSupport {
|
||||
|
||||
public boolean consumeAll = false;
|
||||
public int deliveryMode = DeliveryMode.NON_PERSISTENT;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AMQ2314Test.class);
|
||||
private static final int MESSAGES_COUNT = 30000;
|
||||
private static byte[] buf = new byte[1024];
|
||||
private BrokerService broker;
|
||||
private String connectionUri;
|
||||
|
||||
private static final long messageReceiveTimeout = 500L;
|
||||
|
||||
Destination destination = new ActiveMQTopic("FooTwo");
|
||||
|
||||
public void testRemoveSlowSubscriberWhacksTempStore() throws Exception {
|
||||
runProducerWithHungConsumer();
|
||||
}
|
||||
|
||||
public void testMemoryUsageReleasedOnAllConsumed() throws Exception {
|
||||
consumeAll = true;
|
||||
runProducerWithHungConsumer();
|
||||
// do it again to ensure memory limits are decreased
|
||||
runProducerWithHungConsumer();
|
||||
}
|
||||
|
||||
public void runProducerWithHungConsumer() throws Exception {
|
||||
|
||||
final CountDownLatch consumerContinue = new CountDownLatch(1);
|
||||
final CountDownLatch consumerReady = new CountDownLatch(1);
|
||||
|
||||
final long origTempUsage = broker.getSystemUsage().getTempUsage().getUsage();
|
||||
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(connectionUri);
|
||||
factory.setAlwaysSyncSend(true);
|
||||
|
||||
// ensure messages are spooled to disk for this consumer
|
||||
ActiveMQPrefetchPolicy prefetch = new ActiveMQPrefetchPolicy();
|
||||
prefetch.setTopicPrefetch(500);
|
||||
factory.setPrefetchPolicy(prefetch);
|
||||
final Connection connection = factory.createConnection();
|
||||
connection.start();
|
||||
|
||||
Thread producingThread = new Thread("Producing thread") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
producer.setDeliveryMode(deliveryMode);
|
||||
for (int idx = 0; idx < MESSAGES_COUNT; ++idx) {
|
||||
Message message = session.createTextMessage(new String(buf) + idx);
|
||||
producer.send(message);
|
||||
}
|
||||
producer.close();
|
||||
session.close();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Thread consumingThread = new Thread("Consuming thread") {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
int count = 0;
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer consumer = session.createConsumer(destination);
|
||||
|
||||
while (consumer.receive(messageReceiveTimeout) == null) {
|
||||
consumerReady.countDown();
|
||||
}
|
||||
count++;
|
||||
LOG.info("Received one... waiting");
|
||||
consumerContinue.await();
|
||||
if (consumeAll) {
|
||||
LOG.info("Consuming the rest of the messages...");
|
||||
while (consumer.receive(messageReceiveTimeout) != null) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
LOG.info("consumer session closing: consumed count: " + count);
|
||||
session.close();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
consumingThread.start();
|
||||
consumerReady.await();
|
||||
|
||||
producingThread.start();
|
||||
producingThread.join();
|
||||
|
||||
final long tempUsageBySubscription = broker.getSystemUsage().getTempUsage().getUsage();
|
||||
LOG.info("Orig Usage: " + origTempUsage + ", currentUsage: " + tempUsageBySubscription);
|
||||
assertTrue("some temp store has been used", tempUsageBySubscription != origTempUsage);
|
||||
consumerContinue.countDown();
|
||||
consumingThread.join();
|
||||
connection.close();
|
||||
|
||||
LOG.info("Subscription Usage: " + tempUsageBySubscription + ", endUsage: " + broker.getSystemUsage().getTempUsage().getUsage());
|
||||
|
||||
assertTrue("temp usage decreased with removed sub", Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
return broker.getSystemUsage().getTempUsage().getUsage() < tempUsageBySubscription;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setAutoFail(true);
|
||||
super.setUp();
|
||||
broker = new BrokerService();
|
||||
broker.setDataDirectory("target" + File.separator + "activemq-data");
|
||||
broker.setPersistent(true);
|
||||
broker.setUseJmx(true);
|
||||
broker.setAdvisorySupport(false);
|
||||
broker.setDeleteAllMessagesOnStartup(true);
|
||||
broker.getSystemUsage().getMemoryUsage().setLimit(1024L * 1024 * 64);
|
||||
|
||||
broker.addConnector("tcp://localhost:0").setName("Default");
|
||||
broker.start();
|
||||
|
||||
connectionUri = broker.getTransportConnectors().get(0).getPublishableConnectString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
broker.stop();
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return suite(AMQ2314Test.class);
|
||||
}
|
||||
}
|
|
@ -1,192 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
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 junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
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;
|
||||
import org.apache.activemq.store.kahadb.KahaDBStore;
|
||||
|
||||
/*
|
||||
AMQ2356Test
|
||||
We have an environment where we have a very large number of destinations.
|
||||
In an effort to reduce the number of threads I have set the options
|
||||
-Dorg.apache.activemq.UseDedicatedTaskRunner=false
|
||||
|
||||
and
|
||||
|
||||
<policyEntry queue=">" optimizedDispatch="true"/>
|
||||
|
||||
Unfortunately this very quickly leads to deadlocked queues.
|
||||
|
||||
My environment is:
|
||||
|
||||
ActiveMQ 5.2 Ubunty Jaunty kernel 2.6.28-14-generic #47-Ubuntu SMP (although only a single core on my system)
|
||||
TCP transportConnector
|
||||
|
||||
To reproduce the bug (which I can do 100% of the time) I connect 5 consumers (AUTO_ACK) to 5 different queues.
|
||||
Then I start 5 producers and pair them up with a consumer on a queue, and they start sending PERSISTENT messages.
|
||||
I've set the producer to send 100 messages and disconnect, and the consumer to receive 100 messages and disconnect.
|
||||
The first pair usually gets through their 100 messages and disconnect, at which point all the other pairs have
|
||||
deadlocked at less than 30 messages each.
|
||||
*/
|
||||
public class AMQ2356Test extends TestCase {
|
||||
|
||||
protected static final int MESSAGE_COUNT = 1000;
|
||||
protected static final int NUMBER_OF_PAIRS = 10;
|
||||
protected BrokerService broker;
|
||||
protected String brokerURL = ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL;
|
||||
protected int destinationCount;
|
||||
|
||||
public void testScenario() throws Exception {
|
||||
for (int i = 0; i < NUMBER_OF_PAIRS; i++) {
|
||||
ActiveMQQueue queue = new ActiveMQQueue(getClass().getName() + ":" + i);
|
||||
ProducerConsumerPair cp = new ProducerConsumerPair();
|
||||
cp.start(this.brokerURL, queue, MESSAGE_COUNT);
|
||||
cp.testRun();
|
||||
cp.stop();
|
||||
}
|
||||
}
|
||||
|
||||
protected Destination getDestination(Session session) throws JMSException {
|
||||
String destinationName = getClass().getName() + "." + destinationCount++;
|
||||
return session.createQueue(destinationName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
if (broker == null) {
|
||||
broker = createBroker();
|
||||
}
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
}
|
||||
}
|
||||
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService answer = new BrokerService();
|
||||
configureBroker(answer);
|
||||
answer.start();
|
||||
return answer;
|
||||
}
|
||||
|
||||
protected void configureBroker(BrokerService answer) throws Exception {
|
||||
File dataFileDir = new File("target/test-amq-data/bugs/AMQ2356/kahadb");
|
||||
KahaDBStore kaha = new KahaDBStore();
|
||||
kaha.setDirectory(dataFileDir);
|
||||
answer.setUseJmx(false);
|
||||
// Setup a destination policy where it takes only 1 message at a time.
|
||||
PolicyMap policyMap = new PolicyMap();
|
||||
PolicyEntry policy = new PolicyEntry();
|
||||
policy.setOptimizedDispatch(true);
|
||||
policyMap.setDefaultEntry(policy);
|
||||
answer.setDestinationPolicy(policyMap);
|
||||
|
||||
answer.setAdvisorySupport(false);
|
||||
answer.setEnableStatistics(false);
|
||||
answer.setDeleteAllMessagesOnStartup(true);
|
||||
answer.addConnector(brokerURL);
|
||||
|
||||
}
|
||||
|
||||
static class ProducerConsumerPair {
|
||||
|
||||
private Destination destination;
|
||||
private MessageProducer producer;
|
||||
private MessageConsumer consumer;
|
||||
private Connection producerConnection;
|
||||
private Connection consumerConnection;
|
||||
private int numberOfMessages;
|
||||
|
||||
ProducerConsumerPair() {
|
||||
|
||||
}
|
||||
|
||||
void start(String brokerURL, final Destination dest, int msgNum) throws Exception {
|
||||
this.destination = dest;
|
||||
this.numberOfMessages = msgNum;
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(brokerURL);
|
||||
this.producerConnection = cf.createConnection();
|
||||
this.producerConnection.start();
|
||||
this.consumerConnection = cf.createConnection();
|
||||
this.consumerConnection.start();
|
||||
this.producer = createProducer(this.producerConnection);
|
||||
this.consumer = createConsumer(this.consumerConnection);
|
||||
}
|
||||
|
||||
void testRun() throws Exception {
|
||||
|
||||
Session s = this.producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
for (int i = 0; i < this.numberOfMessages; i++) {
|
||||
BytesMessage msg = s.createBytesMessage();
|
||||
msg.writeBytes(new byte[1024]);
|
||||
this.producer.send(msg);
|
||||
}
|
||||
int received = 0;
|
||||
for (int i = 0; i < this.numberOfMessages; i++) {
|
||||
Message msg = this.consumer.receive();
|
||||
assertNotNull(msg);
|
||||
received++;
|
||||
}
|
||||
assertEquals("Messages received on " + this.destination, this.numberOfMessages, received);
|
||||
|
||||
}
|
||||
|
||||
void stop() throws Exception {
|
||||
if (this.producerConnection != null) {
|
||||
this.producerConnection.close();
|
||||
}
|
||||
if (this.consumerConnection != null) {
|
||||
this.consumerConnection.close();
|
||||
}
|
||||
}
|
||||
|
||||
private MessageProducer createProducer(Connection connection) throws Exception {
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer result = session.createProducer(this.destination);
|
||||
return result;
|
||||
}
|
||||
|
||||
private MessageConsumer createConsumer(Connection connection) throws Exception {
|
||||
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer result = session.createConsumer(this.destination);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
//package org.apache.activemq.transport.failover;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
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 org.apache.activemq.ActiveMQConnection;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ConnectionId;
|
||||
import org.apache.activemq.state.ConnectionState;
|
||||
import org.apache.activemq.state.ConnectionStateTracker;
|
||||
import org.apache.activemq.state.TransactionState;
|
||||
import org.apache.activemq.transport.MutexTransport;
|
||||
import org.apache.activemq.transport.ResponseCorrelator;
|
||||
import org.apache.activemq.transport.failover.FailoverTransport;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AMQ2364Test {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testRollbackLeak() throws Exception {
|
||||
|
||||
int messageCount = 1000;
|
||||
URI failoverUri = new URI("failover:(vm://localhost)?jms.redeliveryPolicy.maximumRedeliveries=0");
|
||||
|
||||
Destination dest = new ActiveMQQueue("Failover.Leak");
|
||||
|
||||
ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(failoverUri);
|
||||
ActiveMQConnection connection = (ActiveMQConnection) cf.createConnection();
|
||||
connection.start();
|
||||
final Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
|
||||
MessageProducer producer = session.createProducer(dest);
|
||||
|
||||
for (int i = 0; i < messageCount; ++i)
|
||||
producer.send(session.createTextMessage("Test message #" + i));
|
||||
producer.close();
|
||||
session.commit();
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(dest);
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(messageCount);
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
|
||||
@Override
|
||||
public void onMessage(Message msg) {
|
||||
try {
|
||||
session.rollback();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
latch.await();
|
||||
consumer.close();
|
||||
session.close();
|
||||
|
||||
ResponseCorrelator respCorr = (ResponseCorrelator) connection.getTransport();
|
||||
MutexTransport mutexTrans = (MutexTransport) respCorr.getNext();
|
||||
FailoverTransport failoverTrans = (FailoverTransport) mutexTrans.getNext();
|
||||
Field stateTrackerField = FailoverTransport.class.getDeclaredField("stateTracker");
|
||||
stateTrackerField.setAccessible(true);
|
||||
ConnectionStateTracker stateTracker = (ConnectionStateTracker) stateTrackerField.get(failoverTrans);
|
||||
Field statesField = ConnectionStateTracker.class.getDeclaredField("connectionStates");
|
||||
statesField.setAccessible(true);
|
||||
ConcurrentHashMap<ConnectionId, ConnectionState> states = (ConcurrentHashMap<ConnectionId, ConnectionState>) statesField.get(stateTracker);
|
||||
|
||||
ConnectionState state = states.get(connection.getConnectionInfo().getConnectionId());
|
||||
|
||||
Collection<TransactionState> transactionStates = state.getTransactionStates();
|
||||
|
||||
connection.stop();
|
||||
connection.close();
|
||||
|
||||
assertEquals("Transaction states not cleaned up", 0, transactionStates.size());
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.command.ActiveMQDestination;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AMQ2383Test {
|
||||
|
||||
@Test
|
||||
public void activeMQTest() throws Exception {
|
||||
Destination dest = ActiveMQDestination.createDestination("testQueue", ActiveMQDestination.QUEUE_TYPE);
|
||||
ConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost?broker.useJmx=false&broker.persistent=false");
|
||||
Connection producerConnection = factory.createConnection();
|
||||
producerConnection.start();
|
||||
Connection consumerConnection = factory.createConnection();
|
||||
consumerConnection.start();
|
||||
|
||||
Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = producerSession.createProducer(dest);
|
||||
TextMessage sentMsg = producerSession.createTextMessage("test...");
|
||||
producer.send(sentMsg);
|
||||
producerSession.close();
|
||||
|
||||
Session consumerSession = consumerConnection.createSession(true, Session.SESSION_TRANSACTED);
|
||||
MessageConsumer consumer = consumerSession.createConsumer(dest);
|
||||
TextMessage receivedMsg = (TextMessage) consumer.receive();
|
||||
consumerSession.rollback();
|
||||
consumerSession.close();
|
||||
|
||||
assertEquals(sentMsg, receivedMsg);
|
||||
|
||||
producerConnection.close();
|
||||
consumerConnection.close();
|
||||
}
|
||||
}
|
|
@ -1,235 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnection;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
||||
import org.apache.activemq.broker.region.policy.VMPendingQueueMessageStoragePolicy;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* An AMQ-2401 Test
|
||||
*/
|
||||
public class AMQ2401Test extends TestCase implements MessageListener {
|
||||
|
||||
private BrokerService broker;
|
||||
private ActiveMQConnectionFactory factory;
|
||||
private static final int SEND_COUNT = 500;
|
||||
private static final int CONSUMER_COUNT = 50;
|
||||
private static final int PRODUCER_COUNT = 1;
|
||||
private static final int LOG_INTERVAL = 10;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AMQ2401Test.class);
|
||||
|
||||
private final ArrayList<Service> services = new ArrayList<>(CONSUMER_COUNT + PRODUCER_COUNT);
|
||||
private int count = 0;
|
||||
private CountDownLatch latch;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
broker = new BrokerService();
|
||||
broker.setDataDirectory("target" + File.separator + "test-data" + File.separator + "AMQ2401Test");
|
||||
broker.setDeleteAllMessagesOnStartup(true);
|
||||
String connectionUri = broker.addConnector("tcp://0.0.0.0:0").getPublishableConnectString();
|
||||
PolicyMap policies = new PolicyMap();
|
||||
PolicyEntry entry = new PolicyEntry();
|
||||
entry.setMemoryLimit(1024 * 100);
|
||||
entry.setProducerFlowControl(true);
|
||||
entry.setPendingQueuePolicy(new VMPendingQueueMessageStoragePolicy());
|
||||
entry.setQueue(">");
|
||||
policies.setDefaultEntry(entry);
|
||||
broker.setDestinationPolicy(policies);
|
||||
broker.setUseJmx(false);
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
|
||||
factory = new ActiveMQConnectionFactory(connectionUri);
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
}
|
||||
|
||||
public void testDupsOk() throws Exception {
|
||||
|
||||
latch = new CountDownLatch(SEND_COUNT);
|
||||
|
||||
for (int i = 0; i < CONSUMER_COUNT; i++) {
|
||||
TestConsumer consumer = new TestConsumer();
|
||||
consumer.start();
|
||||
services.add(consumer);
|
||||
}
|
||||
for (int i = 0; i < PRODUCER_COUNT; i++) {
|
||||
TestProducer producer = new TestProducer();
|
||||
producer.start();
|
||||
services.add(producer);
|
||||
}
|
||||
|
||||
waitForMessageReceipt(TimeUnit.SECONDS.toMillis(30));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
latch.countDown();
|
||||
if (++count % LOG_INTERVAL == 0) {
|
||||
LOG.debug("Received message " + count);
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InterruptedException
|
||||
* @throws TimeoutException
|
||||
*/
|
||||
private void waitForMessageReceipt(long timeout) throws InterruptedException, TimeoutException {
|
||||
if (!latch.await(timeout, TimeUnit.MILLISECONDS)) {
|
||||
throw new TimeoutException(String.format("Consumner didn't receive expected # of messages, %d of %d received.", latch.getCount(), SEND_COUNT));
|
||||
}
|
||||
}
|
||||
|
||||
private interface Service {
|
||||
|
||||
public void start() throws Exception;
|
||||
|
||||
public void close();
|
||||
}
|
||||
|
||||
private class TestProducer implements Runnable, Service {
|
||||
|
||||
Thread thread;
|
||||
BytesMessage message;
|
||||
|
||||
Connection connection;
|
||||
Session session;
|
||||
MessageProducer producer;
|
||||
|
||||
TestProducer() throws Exception {
|
||||
thread = new Thread(this, "TestProducer");
|
||||
connection = factory.createConnection();
|
||||
connection.start();
|
||||
session = connection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
|
||||
producer = session.createProducer(session.createQueue("AMQ2401Test"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
thread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
int count = SEND_COUNT / PRODUCER_COUNT;
|
||||
for (int i = 1; i <= count; i++) {
|
||||
try {
|
||||
if ((i % LOG_INTERVAL) == 0) {
|
||||
LOG.debug("Sending: " + i);
|
||||
}
|
||||
message = session.createBytesMessage();
|
||||
message.writeBytes(new byte[1024]);
|
||||
producer.send(message);
|
||||
}
|
||||
catch (JMSException jmse) {
|
||||
jmse.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
connection.close();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class TestConsumer implements Runnable, Service {
|
||||
|
||||
ActiveMQConnection connection;
|
||||
Session session;
|
||||
MessageConsumer consumer;
|
||||
|
||||
TestConsumer() throws Exception {
|
||||
factory.setOptimizeAcknowledge(false);
|
||||
connection = (ActiveMQConnection) factory.createConnection();
|
||||
|
||||
session = connection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
|
||||
consumer = session.createConsumer(session.createQueue("AMQ2401Test"));
|
||||
|
||||
consumer.setMessageListener(AMQ2401Test.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws Exception {
|
||||
connection.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
connection.close();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (latch.getCount() > 0) {
|
||||
try {
|
||||
onMessage(consumer.receive());
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,344 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
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.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnection;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.CombinationTestSupport;
|
||||
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.broker.region.policy.VMPendingQueueMessageStoragePolicy;
|
||||
import org.apache.activemq.command.MessageId;
|
||||
import org.apache.activemq.command.ProducerId;
|
||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AMQ2413Test extends CombinationTestSupport implements MessageListener {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AMQ2413Test.class);
|
||||
BrokerService broker;
|
||||
private ActiveMQConnectionFactory factory;
|
||||
|
||||
private static final int HANG_THRESHOLD = 60;
|
||||
private static final int SEND_COUNT = 1000;
|
||||
private static final int RECEIVER_THINK_TIME = 1;
|
||||
private static final int CONSUMER_COUNT = 1;
|
||||
private static final int PRODUCER_COUNT = 50;
|
||||
private static final int TO_SEND = SEND_COUNT / PRODUCER_COUNT;
|
||||
|
||||
public int deliveryMode = DeliveryMode.NON_PERSISTENT;
|
||||
public int ackMode = Session.DUPS_OK_ACKNOWLEDGE;
|
||||
public boolean useVMCursor = false;
|
||||
public boolean useOptimizeAcks = false;
|
||||
|
||||
private final ArrayList<Service> services = new ArrayList<>(CONSUMER_COUNT + PRODUCER_COUNT);
|
||||
AtomicInteger count = new AtomicInteger(0);
|
||||
Semaphore receivedMessages;
|
||||
AtomicBoolean running = new AtomicBoolean(false);
|
||||
|
||||
public void initCombos() {
|
||||
addCombinationValues("deliveryMode", new Object[]{DeliveryMode.PERSISTENT, DeliveryMode.NON_PERSISTENT});
|
||||
addCombinationValues("ackMode", new Object[]{Session.DUPS_OK_ACKNOWLEDGE, Session.AUTO_ACKNOWLEDGE});
|
||||
addCombinationValues("useVMCursor", new Object[]{true, false});
|
||||
// addCombinationValues("useOptimizeAcks", new Object[] {true, false});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
broker = new BrokerService();
|
||||
broker.setDataDirectory("target" + File.separator + "test-data" + File.separator + "AMQ2401Test");
|
||||
broker.setDeleteAllMessagesOnStartup(true);
|
||||
|
||||
KahaDBPersistenceAdapter kahaDb = (KahaDBPersistenceAdapter) broker.getPersistenceAdapter();
|
||||
kahaDb.setConcurrentStoreAndDispatchQueues(false);
|
||||
broker.addConnector("tcp://0.0.0.0:2401");
|
||||
PolicyMap policies = new PolicyMap();
|
||||
PolicyEntry entry = new PolicyEntry();
|
||||
entry.setMemoryLimit(1024 * 1024);
|
||||
entry.setProducerFlowControl(true);
|
||||
if (useVMCursor) {
|
||||
entry.setPendingQueuePolicy(new VMPendingQueueMessageStoragePolicy());
|
||||
}
|
||||
entry.setQueue(">");
|
||||
policies.setDefaultEntry(entry);
|
||||
broker.setDestinationPolicy(policies);
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
|
||||
count.set(0);
|
||||
receivedMessages = new Semaphore(0);
|
||||
|
||||
factory = new ActiveMQConnectionFactory("tcp://0.0.0.0:2401");
|
||||
// factory = new ActiveMQConnectionFactory("vm://localhost?broker.useJmx=false&broker.persistent=false");
|
||||
setAutoFail(true);
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
running.set(false);
|
||||
for (Service service : services) {
|
||||
service.close();
|
||||
}
|
||||
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testReceipt() throws Exception {
|
||||
|
||||
running.set(true);
|
||||
|
||||
for (int i = 0; i < CONSUMER_COUNT; i++) {
|
||||
TestConsumer consumer = new TestConsumer();
|
||||
consumer.start();
|
||||
services.add(consumer);
|
||||
}
|
||||
for (int i = 0; i < PRODUCER_COUNT; i++) {
|
||||
TestProducer producer = new TestProducer(i);
|
||||
producer.start();
|
||||
services.add(producer);
|
||||
}
|
||||
|
||||
waitForMessageReceipt();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see javax.jms.MessageListener#onMessage(javax.jms.Message)
|
||||
*/
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
receivedMessages.release();
|
||||
if (count.incrementAndGet() % 100 == 0) {
|
||||
LOG.info("Received message " + count);
|
||||
}
|
||||
track(message);
|
||||
if (RECEIVER_THINK_TIME > 0) {
|
||||
try {
|
||||
Thread.sleep(RECEIVER_THINK_TIME);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HashMap<ProducerId, boolean[]> tracker = new HashMap<>();
|
||||
|
||||
private synchronized void track(Message message) {
|
||||
try {
|
||||
MessageId id = new MessageId(message.getJMSMessageID());
|
||||
ProducerId pid = id.getProducerId();
|
||||
int seq = (int) id.getProducerSequenceId();
|
||||
boolean[] ids = tracker.get(pid);
|
||||
if (ids == null) {
|
||||
ids = new boolean[TO_SEND + 1];
|
||||
ids[seq] = true;
|
||||
tracker.put(pid, ids);
|
||||
}
|
||||
else {
|
||||
assertTrue("not already received: " + id, !ids[seq]);
|
||||
ids[seq] = true;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InterruptedException
|
||||
* @throws TimeoutException
|
||||
*/
|
||||
private void waitForMessageReceipt() throws InterruptedException, TimeoutException {
|
||||
try {
|
||||
while (count.get() < SEND_COUNT) {
|
||||
if (!receivedMessages.tryAcquire(HANG_THRESHOLD, TimeUnit.SECONDS)) {
|
||||
if (count.get() == SEND_COUNT)
|
||||
break;
|
||||
verifyTracking();
|
||||
throw new TimeoutException("@count=" + count.get() + " Message not received for more than " + HANG_THRESHOLD + " seconds");
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
running.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyTracking() {
|
||||
Vector<MessageId> missing = new Vector<>();
|
||||
for (ProducerId pid : tracker.keySet()) {
|
||||
boolean[] ids = tracker.get(pid);
|
||||
for (int i = 1; i < TO_SEND + 1; i++) {
|
||||
if (!ids[i]) {
|
||||
missing.add(new MessageId(pid, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue("No missing messages: " + missing, missing.isEmpty());
|
||||
}
|
||||
|
||||
private interface Service {
|
||||
|
||||
public void start() throws Exception;
|
||||
|
||||
public void close();
|
||||
}
|
||||
|
||||
private class TestProducer implements Runnable, Service {
|
||||
|
||||
Thread thread;
|
||||
BytesMessage message;
|
||||
Connection connection;
|
||||
Session session;
|
||||
MessageProducer producer;
|
||||
|
||||
TestProducer(int id) throws Exception {
|
||||
thread = new Thread(this, "TestProducer-" + id);
|
||||
connection = factory.createConnection();
|
||||
connection.start();
|
||||
session = connection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
|
||||
producer = session.createProducer(session.createQueue("AMQ2401Test"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
thread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
int i = 1;
|
||||
for (; i <= TO_SEND; i++) {
|
||||
try {
|
||||
|
||||
if (+i % 100 == 0) {
|
||||
LOG.info(Thread.currentThread().getName() + " Sending message " + i);
|
||||
}
|
||||
message = session.createBytesMessage();
|
||||
message.writeBytes(new byte[1024]);
|
||||
producer.setDeliveryMode(deliveryMode);
|
||||
producer.send(message);
|
||||
}
|
||||
catch (JMSException jmse) {
|
||||
jmse.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOG.info(Thread.currentThread().getName() + " Sent: " + (i - 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
connection.close();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class TestConsumer implements Runnable, Service {
|
||||
|
||||
ActiveMQConnection connection;
|
||||
Session session;
|
||||
MessageConsumer consumer;
|
||||
|
||||
TestConsumer() throws Exception {
|
||||
factory.setOptimizeAcknowledge(false);
|
||||
connection = (ActiveMQConnection) factory.createConnection();
|
||||
if (useOptimizeAcks) {
|
||||
connection.setOptimizeAcknowledge(true);
|
||||
}
|
||||
|
||||
session = connection.createSession(false, ackMode);
|
||||
consumer = session.createConsumer(session.createQueue("AMQ2401Test"));
|
||||
|
||||
consumer.setMessageListener(AMQ2413Test.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws Exception {
|
||||
connection.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
connection.close();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
while (running.get()) {
|
||||
try {
|
||||
onMessage(consumer.receive());
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return suite(AMQ2413Test.class);
|
||||
}
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.apache.activemq.JmsMultipleBrokersTestSupport;
|
||||
import org.apache.activemq.broker.jmx.BrokerView;
|
||||
import org.apache.activemq.util.Wait;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AMQ2439Test extends JmsMultipleBrokersTestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AMQ2439Test.class);
|
||||
Destination dest;
|
||||
|
||||
public void testDuplicatesThroughNetwork() throws Exception {
|
||||
assertEquals("received expected amount", 500, receiveExactMessages("BrokerB", 500));
|
||||
assertEquals("received expected amount", 500, receiveExactMessages("BrokerB", 500));
|
||||
validateQueueStats();
|
||||
}
|
||||
|
||||
private void validateQueueStats() throws Exception {
|
||||
final BrokerView brokerView = brokers.get("BrokerA").broker.getAdminView();
|
||||
assertEquals("enequeue is correct", 1000, brokerView.getTotalEnqueueCount());
|
||||
|
||||
assertTrue("dequeue is correct", Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
LOG.info("dequeue count (want 1000), is : " + brokerView.getTotalDequeueCount());
|
||||
return 1000 == brokerView.getTotalDequeueCount();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
protected int receiveExactMessages(String brokerName, int msgCount) throws Exception {
|
||||
|
||||
BrokerItem brokerItem = brokers.get(brokerName);
|
||||
Connection connection = brokerItem.createConnection();
|
||||
connection.start();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer consumer = session.createConsumer(dest);
|
||||
|
||||
Message msg;
|
||||
int i;
|
||||
for (i = 0; i < msgCount; i++) {
|
||||
msg = consumer.receive(1000);
|
||||
if (msg == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
connection.close();
|
||||
brokerItem.connections.remove(connection);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
createBroker(new URI("broker:(tcp://localhost:61616)/BrokerA?persistent=true&deleteAllMessagesOnStartup=true&advisorySupport=false"));
|
||||
createBroker(new URI("broker:(tcp://localhost:61617)/BrokerB?persistent=true&deleteAllMessagesOnStartup=true&useJmx=false"));
|
||||
bridgeBrokers("BrokerA", "BrokerB");
|
||||
|
||||
startAllBrokers();
|
||||
|
||||
// Create queue
|
||||
dest = createDestination("TEST.FOO", false);
|
||||
sendMessages("BrokerA", dest, 1000);
|
||||
}
|
||||
}
|
|
@ -1,232 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.ExceptionListener;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.apache.activemq.ActiveMQSession;
|
||||
import org.apache.activemq.TestSupport;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
|
||||
/**
|
||||
* In CLIENT_ACKNOWLEDGE and INDIVIDUAL_ACKNOWLEDGE modes following exception
|
||||
* occurs when ASYNCH consumers acknowledges messages in not in order they
|
||||
* received the messages.
|
||||
* <p>
|
||||
* Exception thrown on broker side:
|
||||
* <p>
|
||||
* {@code javax.jms.JMSException: Could not correlate acknowledgment with
|
||||
* dispatched message: MessageAck}
|
||||
*
|
||||
* @author daroo
|
||||
*/
|
||||
public class AMQ2489Test extends TestSupport {
|
||||
|
||||
private final static String SEQ_NUM_PROPERTY = "seqNum";
|
||||
|
||||
private final static int TOTAL_MESSAGES_CNT = 2;
|
||||
private final static int CONSUMERS_CNT = 2;
|
||||
|
||||
private final CountDownLatch LATCH = new CountDownLatch(TOTAL_MESSAGES_CNT);
|
||||
|
||||
private Connection connection;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
connection = createConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
connection = null;
|
||||
}
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testUnorderedClientAcknowledge() throws Exception {
|
||||
doUnorderedAck(Session.CLIENT_ACKNOWLEDGE);
|
||||
}
|
||||
|
||||
public void testUnorderedIndividualAcknowledge() throws Exception {
|
||||
doUnorderedAck(ActiveMQSession.INDIVIDUAL_ACKNOWLEDGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main test method
|
||||
*
|
||||
* @param acknowledgmentMode - ACK mode to be used by consumers
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void doUnorderedAck(int acknowledgmentMode) throws Exception {
|
||||
List<Consumer> consumers = null;
|
||||
Session producerSession = null;
|
||||
|
||||
connection.start();
|
||||
// Because exception is thrown on broker side only, let's set up
|
||||
// exception listener to get it
|
||||
final TestExceptionListener exceptionListener = new TestExceptionListener();
|
||||
connection.setExceptionListener(exceptionListener);
|
||||
try {
|
||||
consumers = new ArrayList<>();
|
||||
// start customers
|
||||
for (int i = 0; i < CONSUMERS_CNT; i++) {
|
||||
consumers.add(new Consumer(acknowledgmentMode));
|
||||
}
|
||||
|
||||
// produce few test messages
|
||||
producerSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final MessageProducer producer = producerSession.createProducer(new ActiveMQQueue(getQueueName()));
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
for (int i = 0; i < TOTAL_MESSAGES_CNT; i++) {
|
||||
final Message message = producerSession.createTextMessage("test");
|
||||
// assign each message sequence number
|
||||
message.setIntProperty(SEQ_NUM_PROPERTY, i);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
// during each onMessage() calls consumers decreases the LATCH
|
||||
// counter.
|
||||
//
|
||||
// so, let's wait till all messages are consumed.
|
||||
//
|
||||
LATCH.await();
|
||||
|
||||
// wait a bit more to give exception listener a chance be populated
|
||||
// with
|
||||
// broker's error
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
|
||||
assertFalse(exceptionListener.getStatusText(), exceptionListener.hasExceptions());
|
||||
|
||||
}
|
||||
finally {
|
||||
if (producerSession != null)
|
||||
producerSession.close();
|
||||
|
||||
if (consumers != null) {
|
||||
for (Consumer c : consumers) {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String getQueueName() {
|
||||
return getClass().getName() + "." + getName();
|
||||
}
|
||||
|
||||
public final class Consumer implements MessageListener {
|
||||
|
||||
final Session session;
|
||||
|
||||
private Consumer(int acknowledgmentMode) {
|
||||
try {
|
||||
session = connection.createSession(false, acknowledgmentMode);
|
||||
final Queue queue = session.createQueue(getQueueName() + "?consumer.prefetchSize=1");
|
||||
final MessageConsumer consumer = session.createConsumer(queue);
|
||||
consumer.setMessageListener(this);
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
try {
|
||||
// retrieve sequence number assigned by producer...
|
||||
final int seqNum = message.getIntProperty(SEQ_NUM_PROPERTY);
|
||||
|
||||
// ...and let's delay every second message a little bit before
|
||||
// acknowledgment
|
||||
if ((seqNum % 2) == 0) {
|
||||
System.out.println("Delayed message sequence numeber: " + seqNum);
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
message.acknowledge();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally {
|
||||
// decrease LATCH counter in the main test method.
|
||||
LATCH.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
private void close() {
|
||||
if (session != null) {
|
||||
try {
|
||||
session.close();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class TestExceptionListener implements ExceptionListener {
|
||||
|
||||
private final java.util.Queue<Exception> exceptions = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Override
|
||||
public void onException(JMSException e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
|
||||
public boolean hasExceptions() {
|
||||
return exceptions.isEmpty() == false;
|
||||
}
|
||||
|
||||
public String getStatusText() {
|
||||
final StringBuilder str = new StringBuilder();
|
||||
str.append("Exceptions count on broker side: " + exceptions.size() + ".\nMessages:\n");
|
||||
for (Exception e : exceptions) {
|
||||
str.append(e.getMessage() + "\n\n");
|
||||
}
|
||||
return str.toString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
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.Queue;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.store.kahadb.KahaDBStore;
|
||||
import org.apache.activemq.util.IOHelper;
|
||||
|
||||
public class AMQ2512Test extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private static Connection connection;
|
||||
private final static String QUEUE_NAME = "dee.q";
|
||||
private final static int INITIAL_MESSAGES_CNT = 1000;
|
||||
private final static int WORKER_INTERNAL_ITERATIONS = 100;
|
||||
private final static int TOTAL_MESSAGES_CNT = INITIAL_MESSAGES_CNT * WORKER_INTERNAL_ITERATIONS + INITIAL_MESSAGES_CNT;
|
||||
private final static byte[] payload = new byte[5 * 1024];
|
||||
private final static String TEXT = new String(payload);
|
||||
|
||||
private final static String PRP_INITIAL_ID = "initial-id";
|
||||
private final static String PRP_WORKER_ID = "worker-id";
|
||||
|
||||
private final static CountDownLatch LATCH = new CountDownLatch(TOTAL_MESSAGES_CNT);
|
||||
|
||||
private final static AtomicInteger ON_MSG_COUNTER = new AtomicInteger();
|
||||
|
||||
public void testKahaDBFailure() throws Exception {
|
||||
final ConnectionFactory fac = new ActiveMQConnectionFactory(this.bindAddress);
|
||||
connection = fac.createConnection();
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Queue queue = session.createQueue(QUEUE_NAME);
|
||||
final MessageProducer producer = session.createProducer(queue);
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
connection.start();
|
||||
|
||||
final long startTime = System.nanoTime();
|
||||
|
||||
final List<Consumer> consumers = new ArrayList<>();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
consumers.add(new Consumer("worker-" + i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < INITIAL_MESSAGES_CNT; i++) {
|
||||
final TextMessage msg = session.createTextMessage(TEXT);
|
||||
msg.setStringProperty(PRP_INITIAL_ID, "initial-" + i);
|
||||
producer.send(msg);
|
||||
}
|
||||
|
||||
LATCH.await();
|
||||
final long endTime = System.nanoTime();
|
||||
System.out.println("Total execution time = " + TimeUnit.MILLISECONDS.convert(endTime - startTime, TimeUnit.NANOSECONDS) + " [ms].");
|
||||
System.out.println("Rate = " + TOTAL_MESSAGES_CNT / TimeUnit.SECONDS.convert(endTime - startTime, TimeUnit.NANOSECONDS) + " [msg/s].");
|
||||
|
||||
for (Consumer c : consumers) {
|
||||
c.close();
|
||||
}
|
||||
connection.close();
|
||||
}
|
||||
|
||||
private final static class Consumer implements MessageListener {
|
||||
|
||||
private final String name;
|
||||
private final Session session;
|
||||
private final MessageProducer producer;
|
||||
|
||||
private Consumer(String name) {
|
||||
this.name = name;
|
||||
try {
|
||||
session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
final Queue queue = session.createQueue(QUEUE_NAME + "?consumer.prefetchSize=10");
|
||||
producer = session.createProducer(queue);
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
final MessageConsumer consumer = session.createConsumer(queue);
|
||||
consumer.setMessageListener(this);
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
final TextMessage msg = (TextMessage) message;
|
||||
try {
|
||||
if (!msg.propertyExists(PRP_WORKER_ID)) {
|
||||
for (int i = 0; i < WORKER_INTERNAL_ITERATIONS; i++) {
|
||||
final TextMessage newMsg = session.createTextMessage(msg.getText());
|
||||
newMsg.setStringProperty(PRP_WORKER_ID, name + "-" + i);
|
||||
newMsg.setStringProperty(PRP_INITIAL_ID, msg.getStringProperty(PRP_INITIAL_ID));
|
||||
producer.send(newMsg);
|
||||
}
|
||||
}
|
||||
msg.acknowledge();
|
||||
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally {
|
||||
final int onMsgCounter = ON_MSG_COUNTER.getAndIncrement();
|
||||
if (onMsgCounter % 1000 == 0) {
|
||||
System.out.println("message received: " + onMsgCounter);
|
||||
}
|
||||
LATCH.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
private void close() {
|
||||
if (session != null) {
|
||||
try {
|
||||
session.close();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
bindAddress = "tcp://0.0.0.0:61617";
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
File dataFileDir = new File("target/test-amq-2512/datadb");
|
||||
IOHelper.mkdirs(dataFileDir);
|
||||
IOHelper.deleteChildren(dataFileDir);
|
||||
KahaDBStore kaha = new KahaDBStore();
|
||||
kaha.setDirectory(dataFileDir);
|
||||
BrokerService answer = new BrokerService();
|
||||
answer.setPersistenceAdapter(kaha);
|
||||
|
||||
kaha.setEnableJournalDiskSyncs(false);
|
||||
//kaha.setIndexCacheSize(10);
|
||||
answer.setDataDirectoryFile(dataFileDir);
|
||||
answer.setUseJmx(false);
|
||||
answer.addConnector(bindAddress);
|
||||
return answer;
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.jmx.DestinationViewMBean;
|
||||
import org.apache.activemq.broker.jmx.ManagementContext;
|
||||
|
||||
/**
|
||||
* This unit test verifies an issue when
|
||||
* javax.management.InstanceNotFoundException is thrown after subsequent startups when
|
||||
* managementContext createConnector="false"
|
||||
*/
|
||||
public class AMQ2513Test extends TestCase {
|
||||
|
||||
private BrokerService broker;
|
||||
private String connectionUri;
|
||||
|
||||
void createBroker(boolean deleteAllMessagesOnStartup) throws Exception {
|
||||
broker = new BrokerService();
|
||||
broker.setBrokerName("localhost");
|
||||
broker.setUseJmx(true);
|
||||
broker.setDeleteAllMessagesOnStartup(deleteAllMessagesOnStartup);
|
||||
broker.addConnector("tcp://localhost:0");
|
||||
|
||||
ManagementContext ctx = new ManagementContext();
|
||||
//if createConnector == true everything is fine
|
||||
ctx.setCreateConnector(false);
|
||||
broker.setManagementContext(ctx);
|
||||
|
||||
broker.start();
|
||||
broker.waitUntilStarted();
|
||||
|
||||
connectionUri = broker.getTransportConnectors().get(0).getPublishableConnectString();
|
||||
}
|
||||
|
||||
public void testJmx() throws Exception {
|
||||
createBroker(true);
|
||||
|
||||
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(connectionUri);
|
||||
Connection connection = factory.createConnection();
|
||||
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = session.createProducer(session.createQueue("test"));
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
connection.start();
|
||||
|
||||
producer.send(session.createTextMessage("test123"));
|
||||
|
||||
DestinationViewMBean dv = createView();
|
||||
assertTrue(dv.getQueueSize() > 0);
|
||||
|
||||
connection.close();
|
||||
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
|
||||
createBroker(false);
|
||||
factory = new ActiveMQConnectionFactory(connectionUri);
|
||||
connection = factory.createConnection();
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
producer = session.createProducer(session.createQueue("test"));
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
connection.start();
|
||||
producer.send(session.createTextMessage("test123"));
|
||||
connection.close();
|
||||
|
||||
dv = createView();
|
||||
assertTrue(dv.getQueueSize() > 0);
|
||||
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
|
||||
}
|
||||
|
||||
DestinationViewMBean createView() throws Exception {
|
||||
String domain = "org.apache.activemq";
|
||||
ObjectName name = new ObjectName(domain + ":type=Broker,brokerName=localhost," +
|
||||
"destinationType=Queue,destinationName=test");
|
||||
return (DestinationViewMBean) broker.getManagementContext().newProxyInstance(name, DestinationViewMBean.class, true);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.apache.activemq.broker.region.Queue;
|
||||
import org.junit.Assert;
|
||||
|
||||
/**
|
||||
* This test demonstrates a bug in which calling
|
||||
* Queue#removeMatchingMessages("") generates an exception, whereas the JMS
|
||||
* specification states that an empty selector is valid.
|
||||
*/
|
||||
public class AMQ2528Test extends EmbeddedBrokerTestSupport {
|
||||
|
||||
/**
|
||||
* Setup the test so that the destination is a queue.
|
||||
*/
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
useTopic = false;
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* This test enqueues test messages to destination and then verifies that
|
||||
* {@link Queue#removeMatchingMessages("")} removes all the messages.
|
||||
*/
|
||||
public void testRemoveMatchingMessages() throws Exception {
|
||||
final int NUM_MESSAGES = 100;
|
||||
final String MESSAGE_ID = "id";
|
||||
|
||||
// Enqueue the test messages.
|
||||
Connection conn = createConnection();
|
||||
try {
|
||||
conn.start();
|
||||
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer producer = session.createProducer(destination);
|
||||
for (int id = 0; id < NUM_MESSAGES; id++) {
|
||||
Message message = session.createMessage();
|
||||
message.setIntProperty(MESSAGE_ID, id);
|
||||
producer.send(message);
|
||||
}
|
||||
producer.close();
|
||||
session.close();
|
||||
}
|
||||
finally {
|
||||
conn.close();
|
||||
}
|
||||
|
||||
// Verify that half of the messages can be removed by selector.
|
||||
Queue queue = (Queue) broker.getRegionBroker().getDestinations(destination).iterator().next();
|
||||
|
||||
Assert.assertEquals(NUM_MESSAGES / 2, queue.removeMatchingMessages(MESSAGE_ID + " < " + NUM_MESSAGES / 2));
|
||||
|
||||
// Verify that the remainder of the messages can be removed by empty
|
||||
// selector.
|
||||
Assert.assertEquals(NUM_MESSAGES - NUM_MESSAGES / 2, queue.removeMatchingMessages(""));
|
||||
}
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TemporaryQueue;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
|
||||
public class AMQ2571Test extends EmbeddedBrokerTestSupport {
|
||||
|
||||
public void testTempQueueClosing() {
|
||||
try {
|
||||
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(this.bindAddress);
|
||||
connectionFactory.setAlwaysSyncSend(true);
|
||||
|
||||
// First create session that will own the TempQueue
|
||||
Connection connectionA = connectionFactory.createConnection();
|
||||
connectionA.start();
|
||||
|
||||
Session sessionA = connectionA.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
TemporaryQueue tempQueue = sessionA.createTemporaryQueue();
|
||||
|
||||
// Next, create session that will put messages on the queue.
|
||||
Connection connectionB = connectionFactory.createConnection();
|
||||
connectionB.start();
|
||||
|
||||
Session sessionB = connectionB.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
// Create a producer for connection B.
|
||||
final MessageProducer producerB = sessionB.createProducer(tempQueue);
|
||||
producerB.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
|
||||
|
||||
final TextMessage message = sessionB.createTextMessage("Testing AMQ TempQueue.");
|
||||
|
||||
Thread sendingThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long end = System.currentTimeMillis() + 5 * 60 * 1000;
|
||||
// wait for exception on send
|
||||
while (System.currentTimeMillis() < end) {
|
||||
producerB.send(message);
|
||||
}
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Send 5000 messages.
|
||||
sendingThread.start();
|
||||
// Now close connection A. This will remove the TempQueue.
|
||||
connectionA.close();
|
||||
// Wait for the thread to finish.
|
||||
sendingThread.join(5 * 60 * 1000);
|
||||
|
||||
// Sleep for a while to make sure that we should know that the
|
||||
// TempQueue is gone.
|
||||
//Thread.sleep(50);
|
||||
|
||||
// Now we test if we are able to send again.
|
||||
try {
|
||||
producerB.send(message);
|
||||
fail("Involuntary recreated temporary queue.");
|
||||
}
|
||||
catch (JMSException e) {
|
||||
// Got exception, just as we wanted because the creator of
|
||||
// the TempQueue had closed the connection prior to the send.
|
||||
assertTrue("TempQueue does not exist anymore.", true);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
fail("Unexpected exception " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
bindAddress = "vm://localhost";
|
||||
setAutoFail(true);
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerService createBroker() throws Exception {
|
||||
BrokerService answer = new BrokerService();
|
||||
answer.setPersistent(false);
|
||||
answer.setUseJmx(false);
|
||||
return answer;
|
||||
}
|
||||
}
|
|
@ -1,195 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.ActiveMQPrefetchPolicy;
|
||||
import org.apache.activemq.TestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.jms.Topic;
|
||||
import javax.jms.TopicConnection;
|
||||
import javax.jms.TopicSession;
|
||||
|
||||
public class AMQ2580Test extends TestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AMQ2580Test.class);
|
||||
|
||||
private static final String TOPIC_NAME = "topicName";
|
||||
private static final String CLIENT_ID = "client_id";
|
||||
private static final String textOfSelectedMsg = "good_message";
|
||||
|
||||
protected TopicConnection connection;
|
||||
|
||||
private Topic topic;
|
||||
private Session session;
|
||||
private MessageProducer producer;
|
||||
private ConnectionFactory connectionFactory;
|
||||
private BrokerService service;
|
||||
|
||||
public static Test suite() {
|
||||
return suite(AMQ2580Test.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
initDurableBroker();
|
||||
initConnectionFactory();
|
||||
initTopic();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
shutdownClient();
|
||||
service.stop();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private void initConnection() throws JMSException {
|
||||
if (connection == null) {
|
||||
LOG.info("Initializing connection");
|
||||
|
||||
connection = (TopicConnection) connectionFactory.createConnection();
|
||||
connection.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void initCombosForTestTopicIsDurableSmokeTest() throws Exception {
|
||||
addCombinationValues("defaultPersistenceAdapter", PersistenceAdapterChoice.values());
|
||||
}
|
||||
|
||||
public void testTopicIsDurableSmokeTest() throws Exception {
|
||||
|
||||
initClient();
|
||||
MessageConsumer consumer = createMessageConsumer();
|
||||
LOG.info("Consuming message");
|
||||
assertNull(consumer.receive(1));
|
||||
shutdownClient();
|
||||
consumer.close();
|
||||
|
||||
sendMessages();
|
||||
shutdownClient();
|
||||
|
||||
initClient();
|
||||
consumer = createMessageConsumer();
|
||||
|
||||
LOG.info("Consuming message");
|
||||
TextMessage answer1 = (TextMessage) consumer.receive(1000);
|
||||
assertNotNull("we got our message", answer1);
|
||||
|
||||
consumer.close();
|
||||
}
|
||||
|
||||
private MessageConsumer createMessageConsumer() throws JMSException {
|
||||
LOG.info("creating durable subscriber");
|
||||
return session.createDurableSubscriber(topic, TOPIC_NAME, "name='value'", false);
|
||||
}
|
||||
|
||||
private void initClient() throws JMSException {
|
||||
LOG.info("Initializing client");
|
||||
|
||||
initConnection();
|
||||
initSession();
|
||||
}
|
||||
|
||||
private void shutdownClient() throws JMSException {
|
||||
LOG.info("Closing session and connection");
|
||||
session.close();
|
||||
connection.close();
|
||||
session = null;
|
||||
connection = null;
|
||||
}
|
||||
|
||||
private void sendMessages() throws JMSException {
|
||||
initConnection();
|
||||
|
||||
initSession();
|
||||
|
||||
LOG.info("Creating producer");
|
||||
producer = session.createProducer(topic);
|
||||
|
||||
sendMessageThatFailsSelection();
|
||||
|
||||
sendMessage(textOfSelectedMsg, "value");
|
||||
}
|
||||
|
||||
private void initSession() throws JMSException {
|
||||
LOG.info("Initializing session");
|
||||
session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
}
|
||||
|
||||
private void sendMessageThatFailsSelection() throws JMSException {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
String textOfNotSelectedMsg = "Msg_" + i;
|
||||
sendMessage(textOfNotSelectedMsg, "not_value");
|
||||
LOG.info("#");
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessage(String msgText, String propertyValue) throws JMSException {
|
||||
LOG.info("Creating message: " + msgText);
|
||||
TextMessage messageToSelect = session.createTextMessage(msgText);
|
||||
messageToSelect.setStringProperty("name", propertyValue);
|
||||
LOG.info("Sending message");
|
||||
producer.send(messageToSelect);
|
||||
}
|
||||
|
||||
protected void initConnectionFactory() throws Exception {
|
||||
ActiveMQConnectionFactory activeMqConnectionFactory = createActiveMqConnectionFactory();
|
||||
connectionFactory = activeMqConnectionFactory;
|
||||
}
|
||||
|
||||
private ActiveMQConnectionFactory createActiveMqConnectionFactory() throws Exception {
|
||||
ActiveMQConnectionFactory activeMqConnectionFactory = new ActiveMQConnectionFactory("failover:" + service.getTransportConnectors().get(0).getConnectUri().toString());
|
||||
activeMqConnectionFactory.setWatchTopicAdvisories(false);
|
||||
ActiveMQPrefetchPolicy prefetchPolicy = new ActiveMQPrefetchPolicy();
|
||||
prefetchPolicy.setDurableTopicPrefetch(2);
|
||||
prefetchPolicy.setOptimizeDurableTopicPrefetch(2);
|
||||
activeMqConnectionFactory.setPrefetchPolicy(prefetchPolicy);
|
||||
activeMqConnectionFactory.setClientID(CLIENT_ID);
|
||||
return activeMqConnectionFactory;
|
||||
}
|
||||
|
||||
private void initDurableBroker() throws Exception {
|
||||
service = new BrokerService();
|
||||
setDefaultPersistenceAdapter(service);
|
||||
service.setDeleteAllMessagesOnStartup(true);
|
||||
service.setAdvisorySupport(false);
|
||||
service.setTransportConnectorURIs(new String[]{"tcp://localhost:0"});
|
||||
service.setPersistent(true);
|
||||
service.setUseJmx(false);
|
||||
service.start();
|
||||
|
||||
}
|
||||
|
||||
private void initTopic() throws JMSException {
|
||||
initConnection();
|
||||
TopicSession topicSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
topic = topicSession.createTopic(TOPIC_NAME);
|
||||
}
|
||||
}
|
|
@ -1,268 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Properties;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
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.TopicSubscriber;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnection;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.jmx.BrokerView;
|
||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.store.PersistenceAdapter;
|
||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
||||
import org.apache.activemq.util.IntrospectionSupport;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
// variation on AMQ2584 where the DLQ consumer works in parallel to producer so
|
||||
// that some dups are not suppressed as they are already acked by the consumer
|
||||
// the audit needs to be disabled to allow these dupes to be consumed
|
||||
public class AMQ2584ConcurrentDlqTest extends org.apache.activemq.TestSupport {
|
||||
|
||||
static final Logger LOG = LoggerFactory.getLogger(AMQ2584ConcurrentDlqTest.class);
|
||||
BrokerService broker = null;
|
||||
ActiveMQTopic topic;
|
||||
|
||||
ActiveMQConnection consumerConnection = null, producerConnection = null, dlqConnection = null;
|
||||
Session consumerSession;
|
||||
Session producerSession;
|
||||
MessageProducer producer;
|
||||
Vector<TopicSubscriber> duralbeSubs = new Vector<>();
|
||||
final int numMessages = 1000;
|
||||
final int numDurableSubs = 2;
|
||||
|
||||
String data;
|
||||
private long dlqConsumerLastReceivedTimeStamp;
|
||||
private AtomicLong dlqReceivedCount = new AtomicLong(0);
|
||||
|
||||
// 2 deliveries of each message, 3 producers
|
||||
CountDownLatch redeliveryConsumerLatch = new CountDownLatch(((2 * numMessages) * numDurableSubs) - 1);
|
||||
// should get at least numMessages, possibly more
|
||||
CountDownLatch dlqConsumerLatch = new CountDownLatch((numMessages - 1));
|
||||
|
||||
public void testSize() throws Exception {
|
||||
openConsumer(redeliveryConsumerLatch);
|
||||
openDlqConsumer(dlqConsumerLatch);
|
||||
|
||||
assertEquals(0, broker.getAdminView().getStorePercentUsage());
|
||||
|
||||
for (int i = 0; i < numMessages; i++) {
|
||||
sendMessage(false);
|
||||
}
|
||||
|
||||
final BrokerView brokerView = broker.getAdminView();
|
||||
|
||||
broker.getSystemUsage().getStoreUsage().isFull();
|
||||
LOG.info("store percent usage: " + brokerView.getStorePercentUsage());
|
||||
assertTrue("redelivery consumer got all it needs, remaining: " + redeliveryConsumerLatch.getCount(), redeliveryConsumerLatch.await(60, TimeUnit.SECONDS));
|
||||
assertTrue("dql consumer got all it needs", dlqConsumerLatch.await(60, TimeUnit.SECONDS));
|
||||
closeConsumer();
|
||||
|
||||
LOG.info("Giving dlq a chance to clear down once topic consumer is closed");
|
||||
|
||||
// consumer all of the duplicates that arrived after the first ack
|
||||
closeDlqConsumer();
|
||||
|
||||
//get broker a chance to clean obsolete messages, wait 2*cleanupInterval
|
||||
Thread.sleep(5000);
|
||||
|
||||
FilenameFilter justLogFiles = new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File file, String s) {
|
||||
return s.endsWith(".log");
|
||||
}
|
||||
};
|
||||
int numFiles = ((KahaDBPersistenceAdapter) broker.getPersistenceAdapter()).getDirectory().list(justLogFiles).length;
|
||||
if (numFiles > 2) {
|
||||
LOG.info(Arrays.toString(((KahaDBPersistenceAdapter) broker.getPersistenceAdapter()).getDirectory().list(justLogFiles)));
|
||||
}
|
||||
LOG.info("num files: " + numFiles);
|
||||
assertEquals("kahaDB dir should contain 1 db file,is: " + numFiles, 1, numFiles);
|
||||
}
|
||||
|
||||
private void openConsumer(final CountDownLatch latch) throws Exception {
|
||||
consumerConnection = (ActiveMQConnection) createConnection();
|
||||
consumerConnection.setClientID("cliID");
|
||||
consumerConnection.start();
|
||||
consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
MessageListener listener = new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
latch.countDown();
|
||||
try {
|
||||
consumerSession.recover();
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
ignored.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 1; i <= numDurableSubs; i++) {
|
||||
TopicSubscriber sub = consumerSession.createDurableSubscriber(topic, "subName" + i);
|
||||
sub.setMessageListener(listener);
|
||||
duralbeSubs.add(sub);
|
||||
}
|
||||
}
|
||||
|
||||
private void openDlqConsumer(final CountDownLatch received) throws Exception {
|
||||
|
||||
dlqConnection = (ActiveMQConnection) createConnection();
|
||||
Session dlqSession = dlqConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer dlqConsumer = dlqSession.createConsumer(new ActiveMQQueue("ActiveMQ.DLQ"));
|
||||
dlqConsumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
if (received.getCount() > 0 && received.getCount() % 200 == 0) {
|
||||
LOG.info("remaining on DLQ: " + received.getCount());
|
||||
}
|
||||
received.countDown();
|
||||
dlqConsumerLastReceivedTimeStamp = System.currentTimeMillis();
|
||||
dlqReceivedCount.incrementAndGet();
|
||||
}
|
||||
});
|
||||
dlqConnection.start();
|
||||
}
|
||||
|
||||
private void closeConsumer() throws JMSException {
|
||||
for (TopicSubscriber sub : duralbeSubs) {
|
||||
sub.close();
|
||||
}
|
||||
if (consumerSession != null) {
|
||||
for (int i = 1; i <= numDurableSubs; i++) {
|
||||
consumerSession.unsubscribe("subName" + i);
|
||||
}
|
||||
}
|
||||
if (consumerConnection != null) {
|
||||
consumerConnection.close();
|
||||
consumerConnection = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void closeDlqConsumer() throws JMSException, InterruptedException {
|
||||
final long limit = System.currentTimeMillis() + 30 * 1000;
|
||||
if (dlqConsumerLastReceivedTimeStamp > 0) {
|
||||
while (System.currentTimeMillis() < dlqConsumerLastReceivedTimeStamp + 5000 && System.currentTimeMillis() < limit) {
|
||||
LOG.info("waiting for DLQ do drain, receivedCount: " + dlqReceivedCount);
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
}
|
||||
}
|
||||
if (dlqConnection != null) {
|
||||
dlqConnection.close();
|
||||
dlqConnection = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessage(boolean filter) throws Exception {
|
||||
if (producerConnection == null) {
|
||||
producerConnection = (ActiveMQConnection) createConnection();
|
||||
producerConnection.start();
|
||||
producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
producer = producerSession.createProducer(topic);
|
||||
}
|
||||
|
||||
Message message = producerSession.createMessage();
|
||||
message.setStringProperty("data", data);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
private void startBroker(boolean deleteMessages) throws Exception {
|
||||
broker = new BrokerService();
|
||||
broker.setAdvisorySupport(false);
|
||||
broker.setBrokerName("testStoreSize");
|
||||
|
||||
PolicyMap map = new PolicyMap();
|
||||
PolicyEntry entry = new PolicyEntry();
|
||||
entry.setEnableAudit(false);
|
||||
map.setDefaultEntry(entry);
|
||||
broker.setDestinationPolicy(map);
|
||||
|
||||
if (deleteMessages) {
|
||||
broker.setDeleteAllMessagesOnStartup(true);
|
||||
}
|
||||
configurePersistenceAdapter(broker.getPersistenceAdapter());
|
||||
broker.getSystemUsage().getStoreUsage().setLimit(200 * 1000 * 1000);
|
||||
broker.start();
|
||||
}
|
||||
|
||||
private void configurePersistenceAdapter(PersistenceAdapter persistenceAdapter) {
|
||||
Properties properties = new Properties();
|
||||
String maxFileLengthVal = String.valueOf(2 * 1024 * 1024);
|
||||
properties.put("journalMaxFileLength", maxFileLengthVal);
|
||||
properties.put("maxFileLength", maxFileLengthVal);
|
||||
properties.put("cleanupInterval", "2000");
|
||||
properties.put("checkpointInterval", "2000");
|
||||
// there are problems with duplicate dispatch in the cursor, which maintain
|
||||
// a map of messages. A dup dispatch can be dropped.
|
||||
// see: org.apache.activemq.broker.region.cursors.OrderedPendingList
|
||||
// Adding duplicate detection to the default DLQ strategy removes the problem
|
||||
// which means we can leave the default for concurrent store and dispatch q
|
||||
//properties.put("concurrentStoreAndDispatchQueues", "false");
|
||||
|
||||
IntrospectionSupport.setProperties(persistenceAdapter, properties);
|
||||
}
|
||||
|
||||
private void stopBroker() throws Exception {
|
||||
if (broker != null)
|
||||
broker.stop();
|
||||
broker = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory("vm://testStoreSize?jms.watchTopicAdvisories=false&jms.redeliveryPolicy.maximumRedeliveries=1&jms.redeliveryPolicy.initialRedeliveryDelay=0&waitForStart=5000&create=false");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
StringBuilder sb = new StringBuilder(5000);
|
||||
for (int i = 0; i < 5000; i++) {
|
||||
sb.append('a');
|
||||
}
|
||||
data = sb.toString();
|
||||
|
||||
startBroker(true);
|
||||
topic = (ActiveMQTopic) createDestination();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
stopBroker();
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
|
@ -1,233 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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 org.apache.activemq.ActiveMQConnection;
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.TestSupport;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.jmx.BrokerView;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.apache.activemq.store.PersistenceAdapter;
|
||||
import org.apache.activemq.util.IntrospectionSupport;
|
||||
import org.apache.activemq.util.Wait;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@RunWith(value = Parameterized.class)
|
||||
public class AMQ2584Test extends org.apache.activemq.TestSupport {
|
||||
|
||||
static final Logger LOG = LoggerFactory.getLogger(AMQ2584Test.class);
|
||||
BrokerService broker = null;
|
||||
ActiveMQTopic topic;
|
||||
|
||||
ActiveMQConnection consumerConnection = null, producerConnection = null;
|
||||
Session producerSession;
|
||||
MessageProducer producer;
|
||||
final int minPercentUsageForStore = 3;
|
||||
String data;
|
||||
|
||||
private final TestSupport.PersistenceAdapterChoice persistenceAdapterChoice;
|
||||
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
public static Collection<TestSupport.PersistenceAdapterChoice[]> getTestParameters() {
|
||||
TestSupport.PersistenceAdapterChoice[] kahaDb = {TestSupport.PersistenceAdapterChoice.KahaDB};
|
||||
TestSupport.PersistenceAdapterChoice[] levelDb = {TestSupport.PersistenceAdapterChoice.LevelDB};
|
||||
List<TestSupport.PersistenceAdapterChoice[]> choices = new ArrayList<>();
|
||||
choices.add(kahaDb);
|
||||
choices.add(levelDb);
|
||||
|
||||
return choices;
|
||||
}
|
||||
|
||||
public AMQ2584Test(TestSupport.PersistenceAdapterChoice choice) {
|
||||
this.persistenceAdapterChoice = choice;
|
||||
}
|
||||
|
||||
@Test(timeout = 120000)
|
||||
public void testSize() throws Exception {
|
||||
int messages = 1000;
|
||||
CountDownLatch redeliveryConsumerLatch = new CountDownLatch((messages * 3));
|
||||
openConsumer(redeliveryConsumerLatch);
|
||||
|
||||
assertEquals(0, broker.getAdminView().getStorePercentUsage());
|
||||
|
||||
for (int i = 0; i < messages; i++) {
|
||||
sendMessage(false);
|
||||
}
|
||||
|
||||
final BrokerView brokerView = broker.getAdminView();
|
||||
|
||||
broker.getSystemUsage().getStoreUsage().isFull();
|
||||
LOG.info("store percent usage: " + brokerView.getStorePercentUsage());
|
||||
int storePercentUsage = broker.getAdminView().getStorePercentUsage();
|
||||
assertTrue("some store in use", storePercentUsage > minPercentUsageForStore);
|
||||
|
||||
assertTrue("redelivery consumer got all it needs", redeliveryConsumerLatch.await(60, TimeUnit.SECONDS));
|
||||
closeConsumer();
|
||||
|
||||
// consume from DLQ
|
||||
final CountDownLatch received = new CountDownLatch(messages);
|
||||
consumerConnection = (ActiveMQConnection) createConnection();
|
||||
Session dlqSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageConsumer dlqConsumer = dlqSession.createConsumer(new ActiveMQQueue("ActiveMQ.DLQ"));
|
||||
dlqConsumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
if (received.getCount() % 500 == 0) {
|
||||
LOG.info("remaining on DLQ: " + received.getCount());
|
||||
}
|
||||
received.countDown();
|
||||
}
|
||||
});
|
||||
consumerConnection.start();
|
||||
|
||||
assertTrue("Not all messages reached the DLQ", received.await(60, TimeUnit.SECONDS));
|
||||
|
||||
assertTrue("Store usage exceeds expected usage", Wait.waitFor(new Wait.Condition() {
|
||||
@Override
|
||||
public boolean isSatisified() throws Exception {
|
||||
broker.getSystemUsage().getStoreUsage().isFull();
|
||||
LOG.info("store precent usage: " + brokerView.getStorePercentUsage());
|
||||
return broker.getAdminView().getStorePercentUsage() < minPercentUsageForStore;
|
||||
}
|
||||
}));
|
||||
|
||||
closeConsumer();
|
||||
|
||||
}
|
||||
|
||||
private void openConsumer(final CountDownLatch latch) throws Exception {
|
||||
consumerConnection = (ActiveMQConnection) createConnection();
|
||||
consumerConnection.setClientID("cliID");
|
||||
consumerConnection.start();
|
||||
final Session session = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
MessageListener listener = new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
latch.countDown();
|
||||
try {
|
||||
session.recover();
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
ignored.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
session.createDurableSubscriber(topic, "subName1").setMessageListener(listener);
|
||||
session.createDurableSubscriber(topic, "subName2").setMessageListener(listener);
|
||||
session.createDurableSubscriber(topic, "subName3").setMessageListener(listener);
|
||||
}
|
||||
|
||||
private void closeConsumer() throws JMSException {
|
||||
if (consumerConnection != null)
|
||||
consumerConnection.close();
|
||||
consumerConnection = null;
|
||||
}
|
||||
|
||||
private void sendMessage(boolean filter) throws Exception {
|
||||
if (producerConnection == null) {
|
||||
producerConnection = (ActiveMQConnection) createConnection();
|
||||
producerConnection.start();
|
||||
producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
producer = producerSession.createProducer(topic);
|
||||
}
|
||||
|
||||
Message message = producerSession.createMessage();
|
||||
message.setStringProperty("data", data);
|
||||
producer.send(message);
|
||||
}
|
||||
|
||||
private void startBroker(boolean deleteMessages) throws Exception {
|
||||
broker = new BrokerService();
|
||||
broker.setAdvisorySupport(false);
|
||||
broker.setBrokerName("testStoreSize");
|
||||
|
||||
if (deleteMessages) {
|
||||
broker.setDeleteAllMessagesOnStartup(true);
|
||||
}
|
||||
LOG.info("Starting broker with persistenceAdapterChoice " + persistenceAdapterChoice.toString());
|
||||
setPersistenceAdapter(broker, persistenceAdapterChoice);
|
||||
configurePersistenceAdapter(broker.getPersistenceAdapter());
|
||||
broker.getSystemUsage().getStoreUsage().setLimit(200 * 1000 * 1000);
|
||||
broker.start();
|
||||
}
|
||||
|
||||
private void configurePersistenceAdapter(PersistenceAdapter persistenceAdapter) {
|
||||
Properties properties = new Properties();
|
||||
String maxFileLengthVal = String.valueOf(1 * 1024 * 1024);
|
||||
properties.put("journalMaxFileLength", maxFileLengthVal);
|
||||
properties.put("maxFileLength", maxFileLengthVal);
|
||||
properties.put("cleanupInterval", "2000");
|
||||
properties.put("checkpointInterval", "2000");
|
||||
|
||||
IntrospectionSupport.setProperties(persistenceAdapter, properties);
|
||||
}
|
||||
|
||||
private void stopBroker() throws Exception {
|
||||
if (broker != null)
|
||||
broker.stop();
|
||||
broker = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ActiveMQConnectionFactory createConnectionFactory() throws Exception {
|
||||
return new ActiveMQConnectionFactory("vm://testStoreSize?jms.watchTopicAdvisories=false&jms.redeliveryPolicy.maximumRedeliveries=0&jms.closeTimeout=60000&waitForStart=5000&create=false");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
StringBuilder sb = new StringBuilder(5000);
|
||||
for (int i = 0; i < 5000; i++) {
|
||||
sb.append('a');
|
||||
}
|
||||
data = sb.toString();
|
||||
|
||||
startBroker(true);
|
||||
topic = (ActiveMQTopic) createDestination();
|
||||
}
|
||||
|
||||
@Override
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
stopBroker();
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.EmbeddedBrokerAndConnectionTestSupport;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.command.ActiveMQTextMessage;
|
||||
import org.apache.activemq.command.Message;
|
||||
import org.apache.activemq.spring.ConsumerBean;
|
||||
|
||||
public class AMQ2585Test extends EmbeddedBrokerAndConnectionTestSupport {
|
||||
|
||||
private final Destination destination = new ActiveMQQueue("MyQueue");
|
||||
final static String LENGTH10STRING = "1234567890";
|
||||
private Session session;
|
||||
private MessageProducer producer;
|
||||
private ConsumerBean messageList;
|
||||
|
||||
public void testOneMessageWithProperties() throws Exception {
|
||||
TextMessage message = session.createTextMessage(LENGTH10STRING);
|
||||
message.setStringProperty(LENGTH10STRING, LENGTH10STRING);
|
||||
producer.send(message);
|
||||
|
||||
messageList.assertMessagesArrived(1);
|
||||
|
||||
ActiveMQTextMessage received = ((ActiveMQTextMessage) messageList.flushMessages().get(0));
|
||||
|
||||
assertEquals(LENGTH10STRING, received.getText());
|
||||
assertTrue(received.getProperties().size() > 0);
|
||||
assertTrue(received.propertyExists(LENGTH10STRING));
|
||||
assertEquals(LENGTH10STRING, received.getStringProperty(LENGTH10STRING));
|
||||
|
||||
/**
|
||||
* As specified by getSize(), the size (memory usage) of the body should
|
||||
* be length of text * 2. Unsure of how memory usage is calculated for
|
||||
* properties, but should probably not be less than the sum of (string)
|
||||
* lengths for the key name and value.
|
||||
*/
|
||||
|
||||
final int sizeShouldBeNoLessThan = LENGTH10STRING.length() * 4 + Message.DEFAULT_MINIMUM_MESSAGE_SIZE;
|
||||
assertTrue("Message size was smaller than expected: " + received.getSize(), received.getSize() >= sizeShouldBeNoLessThan);
|
||||
assertFalse(LENGTH10STRING.length() * 2 == received.getSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
bindAddress = bindAddress + "?marshal=true";
|
||||
super.setUp();
|
||||
messageList = new ConsumerBean();
|
||||
messageList.setVerbose(true);
|
||||
|
||||
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
|
||||
MessageConsumer messageConsumer = session.createConsumer(destination);
|
||||
|
||||
messageConsumer.setMessageListener(messageList);
|
||||
|
||||
producer = session.createProducer(destination);
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.broker.region.policy.FilePendingQueueMessageStoragePolicy;
|
||||
import org.apache.activemq.broker.region.policy.PolicyEntry;
|
||||
import org.apache.activemq.broker.region.policy.PolicyMap;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
||||
import org.apache.activemq.util.IOHelper;
|
||||
|
||||
public class AMQ2616Test extends TestCase {
|
||||
|
||||
private static final int NUMBER = 2000;
|
||||
private BrokerService brokerService;
|
||||
private final ArrayList<Thread> threads = new ArrayList<>();
|
||||
private final String ACTIVEMQ_BROKER_BIND = "tcp://0.0.0.0:0";
|
||||
private final AtomicBoolean shutdown = new AtomicBoolean();
|
||||
|
||||
private String connectionUri;
|
||||
|
||||
public void testQueueResourcesReleased() throws Exception {
|
||||
ActiveMQConnectionFactory fac = new ActiveMQConnectionFactory(connectionUri);
|
||||
Connection tempConnection = fac.createConnection();
|
||||
tempConnection.start();
|
||||
Session tempSession = tempConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
Queue tempQueue = tempSession.createTemporaryQueue();
|
||||
|
||||
Connection testConnection = fac.createConnection();
|
||||
long startUsage = brokerService.getSystemUsage().getMemoryUsage().getUsage();
|
||||
Session testSession = testConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
MessageProducer testProducer = testSession.createProducer(tempQueue);
|
||||
byte[] payload = new byte[1024 * 4];
|
||||
for (int i = 0; i < NUMBER; i++) {
|
||||
BytesMessage msg = testSession.createBytesMessage();
|
||||
msg.writeBytes(payload);
|
||||
testProducer.send(msg);
|
||||
}
|
||||
long endUsage = brokerService.getSystemUsage().getMemoryUsage().getUsage();
|
||||
assertFalse(startUsage == endUsage);
|
||||
tempConnection.close();
|
||||
Thread.sleep(1000);
|
||||
endUsage = brokerService.getSystemUsage().getMemoryUsage().getUsage();
|
||||
assertEquals(startUsage, endUsage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
// Start an embedded broker up.
|
||||
brokerService = new BrokerService();
|
||||
|
||||
KahaDBPersistenceAdapter adaptor = new KahaDBPersistenceAdapter();
|
||||
adaptor.setEnableJournalDiskSyncs(false);
|
||||
File file = new File("target/AMQ2616Test");
|
||||
IOHelper.mkdirs(file);
|
||||
IOHelper.deleteChildren(file);
|
||||
adaptor.setDirectory(file);
|
||||
brokerService.setPersistenceAdapter(adaptor);
|
||||
|
||||
PolicyMap policyMap = new PolicyMap();
|
||||
PolicyEntry pe = new PolicyEntry();
|
||||
pe.setMemoryLimit(10 * 1024 * 1024);
|
||||
pe.setOptimizedDispatch(true);
|
||||
pe.setProducerFlowControl(false);
|
||||
pe.setExpireMessagesPeriod(1000);
|
||||
pe.setPendingQueuePolicy(new FilePendingQueueMessageStoragePolicy());
|
||||
policyMap.put(new ActiveMQQueue(">"), pe);
|
||||
brokerService.setDestinationPolicy(policyMap);
|
||||
brokerService.getSystemUsage().getMemoryUsage().setLimit(20 * 1024 * 1024);
|
||||
brokerService.getSystemUsage().getTempUsage().setLimit(200 * 1024 * 1024);
|
||||
brokerService.addConnector(ACTIVEMQ_BROKER_BIND);
|
||||
brokerService.start();
|
||||
brokerService.waitUntilStarted();
|
||||
|
||||
connectionUri = brokerService.getTransportConnectors().get(0).getPublishableConnectString();
|
||||
|
||||
new ActiveMQQueue(getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
// Stop any running threads.
|
||||
shutdown.set(true);
|
||||
for (Thread t : threads) {
|
||||
t.interrupt();
|
||||
t.join();
|
||||
}
|
||||
brokerService.stop();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AMQ2645Test extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AMQ2645Test.class);
|
||||
private final static String QUEUE_NAME = "test.daroo.q";
|
||||
|
||||
public void testWaitForTransportInterruptionProcessingHang() throws Exception {
|
||||
final ConnectionFactory fac = new ActiveMQConnectionFactory("failover:(" + this.bindAddress + ")");
|
||||
final Connection connection = fac.createConnection();
|
||||
try {
|
||||
final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
final Queue queue = session.createQueue(QUEUE_NAME);
|
||||
final MessageProducer producer = session.createProducer(queue);
|
||||
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
|
||||
connection.start();
|
||||
|
||||
producer.send(session.createTextMessage("test"));
|
||||
|
||||
final CountDownLatch afterRestart = new CountDownLatch(1);
|
||||
final CountDownLatch twoNewMessages = new CountDownLatch(1);
|
||||
final CountDownLatch thirdMessageReceived = new CountDownLatch(1);
|
||||
|
||||
final MessageConsumer consumer = session.createConsumer(session.createQueue(QUEUE_NAME));
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
try {
|
||||
afterRestart.await();
|
||||
|
||||
final TextMessage txtMsg = (TextMessage) message;
|
||||
if (txtMsg.getText().equals("test")) {
|
||||
producer.send(session.createTextMessage("test 1"));
|
||||
TimeUnit.SECONDS.sleep(5);
|
||||
// THIS SECOND send() WILL CAUSE CONSUMER DEADLOCK
|
||||
producer.send(session.createTextMessage("test 2"));
|
||||
LOG.info("Two new messages produced.");
|
||||
twoNewMessages.countDown();
|
||||
}
|
||||
else if (txtMsg.getText().equals("test 3")) {
|
||||
thirdMessageReceived.countDown();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e.toString());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
LOG.info("Stopping broker....");
|
||||
broker.stop();
|
||||
|
||||
LOG.info("Creating new broker...");
|
||||
broker = createBroker();
|
||||
startBroker();
|
||||
broker.waitUntilStarted();
|
||||
|
||||
afterRestart.countDown();
|
||||
assertTrue("Consumer is deadlocked!", twoNewMessages.await(60, TimeUnit.SECONDS));
|
||||
|
||||
producer.send(session.createTextMessage("test 3"));
|
||||
assertTrue("Consumer got third message after block", thirdMessageReceived.await(60, TimeUnit.SECONDS));
|
||||
|
||||
}
|
||||
finally {
|
||||
broker.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
bindAddress = "tcp://0.0.0.0:61617";
|
||||
super.setUp();
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.broker.BrokerService;
|
||||
import org.apache.activemq.command.ActiveMQQueue;
|
||||
import org.apache.activemq.store.kahadb.KahaDBPersistenceAdapter;
|
||||
import org.apache.activemq.store.kahadb.KahaDBStore;
|
||||
import org.apache.activemq.util.DefaultIOExceptionHandler;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class AMQ2736Test {
|
||||
|
||||
BrokerService broker;
|
||||
|
||||
@Test
|
||||
public void testRollbackOnRecover() throws Exception {
|
||||
broker = createAndStartBroker(true);
|
||||
DefaultIOExceptionHandler ignoreAllExceptionsIOExHandler = new DefaultIOExceptionHandler();
|
||||
ignoreAllExceptionsIOExHandler.setIgnoreAllErrors(true);
|
||||
broker.setIoExceptionHandler(ignoreAllExceptionsIOExHandler);
|
||||
|
||||
ActiveMQConnectionFactory f = new ActiveMQConnectionFactory("vm://localhost?async=false");
|
||||
f.setAlwaysSyncSend(true);
|
||||
Connection c = f.createConnection();
|
||||
c.start();
|
||||
Session s = c.createSession(true, Session.SESSION_TRANSACTED);
|
||||
MessageProducer p = s.createProducer(new ActiveMQQueue("Tx"));
|
||||
p.send(s.createTextMessage("aa"));
|
||||
|
||||
// kill journal without commit
|
||||
KahaDBPersistenceAdapter pa = (KahaDBPersistenceAdapter) broker.getPersistenceAdapter();
|
||||
KahaDBStore store = pa.getStore();
|
||||
|
||||
assertNotNull("last tx location is present " + store.getInProgressTxLocationRange()[1]);
|
||||
|
||||
// test hack, close the journal to ensure no further journal updates when broker stops
|
||||
// mimic kill -9 in terms of no normal shutdown sequence
|
||||
store.getJournal().close();
|
||||
try {
|
||||
store.close();
|
||||
}
|
||||
catch (Exception expectedLotsAsJournalBorked) {
|
||||
}
|
||||
|
||||
broker.stop();
|
||||
broker.waitUntilStopped();
|
||||
|
||||
// restart with recovery
|
||||
broker = createAndStartBroker(false);
|
||||
|
||||
pa = (KahaDBPersistenceAdapter) broker.getPersistenceAdapter();
|
||||
store = pa.getStore();
|
||||
|
||||
// inflight non xa tx should be rolledback on recovery
|
||||
assertNull("in progress tx location is present ", store.getInProgressTxLocationRange()[0]);
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopBroker() throws Exception {
|
||||
if (broker != null) {
|
||||
broker.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private BrokerService createAndStartBroker(boolean deleteAll) throws Exception {
|
||||
BrokerService broker = new BrokerService();
|
||||
broker.setDeleteAllMessagesOnStartup(deleteAll);
|
||||
broker.setUseJmx(false);
|
||||
broker.getManagementContext().setCreateConnector(false);
|
||||
broker.start();
|
||||
return broker;
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.activemq.bugs;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageListener;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||
import org.apache.activemq.EmbeddedBrokerTestSupport;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AMQ2751Test extends EmbeddedBrokerTestSupport {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AMQ2751Test.class);
|
||||
|
||||
private static String clientIdPrefix = "consumer";
|
||||
private static String queueName = "FOO";
|
||||
|
||||
public void testRecoverRedelivery() throws Exception {
|
||||
|
||||
final CountDownLatch redelivery = new CountDownLatch(6);
|
||||
final ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("failover:(" + broker.getTransportConnectors().get(0).getConnectUri() + ")");
|
||||
try {
|
||||
|
||||
Connection connection = factory.createConnection();
|
||||
String clientId = clientIdPrefix;
|
||||
connection.setClientID(clientId);
|
||||
|
||||
final Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
|
||||
Queue queue = session.createQueue(queueName);
|
||||
|
||||
MessageConsumer consumer = session.createConsumer(queue);
|
||||
|
||||
consumer.setMessageListener(new MessageListener() {
|
||||
@Override
|
||||
public void onMessage(Message message) {
|
||||
try {
|
||||
LOG.info("Got message: " + message.getJMSMessageID());
|
||||
if (message.getJMSRedelivered()) {
|
||||
LOG.info("It's a redelivery.");
|
||||
redelivery.countDown();
|
||||
}
|
||||
LOG.info("calling recover() on the session to force redelivery.");
|
||||
session.recover();
|
||||
}
|
||||
catch (JMSException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
System.out.println("Created queue consumer with clientId " + clientId);
|
||||
connection.start();
|
||||
|
||||
MessageProducer producer = session.createProducer(queue);
|
||||
producer.send(session.createTextMessage("test"));
|
||||
|
||||
assertTrue("we got 6 redeliveries", redelivery.await(20, TimeUnit.SECONDS));
|
||||
|
||||
}
|
||||
finally {
|
||||
broker.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
bindAddress = "tcp://localhost:0";
|
||||
super.setUp();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue