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:
Clebert Suconic 2016-04-01 15:46:20 -04:00 committed by jbertram
parent 7e80cc3586
commit 2e66673048
376 changed files with 6331 additions and 50919 deletions

View File

@ -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>

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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 {

View File

@ -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();
}
}

View File

@ -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();
}

View File

@ -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);
}
}
}
}

View File

@ -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");
}

View File

@ -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) {
}
}
}

View File

@ -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();
}
/**

View File

@ -98,6 +98,7 @@ public class ExclusiveConsumerStartupDestinationTest extends EmbeddedBrokerTestS
}
}
//Exclusive consumer not implemented yet.
public void testFailoverToAnotherExclusiveConsumerCreatedFirst() throws JMSException, InterruptedException {
Connection conn = createConnection(true);

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -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");

View File

@ -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();
}
}

View File

@ -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 {

View File

@ -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());

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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() {

View File

@ -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();
}

View File

@ -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();
}
}
}

View File

@ -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);
}

View File

@ -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());
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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 {

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}
}
}

View File

@ -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";
}
}

View File

@ -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";
}
}

View File

@ -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());
}
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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";
}
}

View File

@ -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;
}
}

View File

@ -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 {
}
}

View File

@ -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 -->

View File

@ -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 -->

View File

@ -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 -->

View File

@ -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 -->

View File

@ -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 -->

View File

@ -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 -->

View File

@ -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));
}
}
}

View File

@ -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();
}
}

View File

@ -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 + ".");
}
}
}
}

View File

@ -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) {
}
}
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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());
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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(""));
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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