/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.store.jdbc;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.jms.Connection;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TopicSubscriber;
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.ActiveMQTopic;
import org.apache.activemq.command.Message;
import org.apache.activemq.command.MessageId;
import org.apache.activemq.store.MessageRecoveryListener;
import org.apache.activemq.store.ProxyTopicMessageStore;
import org.apache.activemq.store.TopicMessageStore;
import org.apache.activemq.util.Wait;
import org.apache.activemq.util.Wait.Condition;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class JDBCPersistenceAdapterExpiredMessageTest {
@Rule
public TemporaryFolder dataFileDir = new TemporaryFolder(new File("target"));
protected BrokerService brokerService;
private AtomicBoolean hasSpaceCalled = new AtomicBoolean();
private int expireSize = 5;
@Before
public void setUp() throws Exception {
hasSpaceCalled.set(false);
brokerService = new BrokerService();
//Wrap the adapter and listener to set a flag to make sure we are calling hasSpace()
//during expiration
JDBCPersistenceAdapter jdbc = new JDBCPersistenceAdapter() {
@Override
public TopicMessageStore createTopicMessageStore(ActiveMQTopic destination) throws IOException {
ProxyTopicMessageStore proxy = new ProxyTopicMessageStore(super.createTopicMessageStore(destination)) {
@Override
public void recover(final MessageRecoveryListener listener) throws Exception {
MessageRecoveryListener delegate = new MessageRecoveryListener() {
@Override
public boolean recoverMessageReference(MessageId ref) throws Exception {
return listener.recoverMessageReference(ref);
}
@Override
public boolean recoverMessage(Message message) throws Exception {
return listener.recoverMessage(message);
}
@Override
public boolean isDuplicate(MessageId ref) {
return listener.isDuplicate(ref);
}
@Override
public boolean hasSpace() {
hasSpaceCalled.set(true);
return listener.hasSpace();
}
};
super.recover(delegate);
}
};
return proxy;
}
};
brokerService.setSchedulerSupport(false);
brokerService.setDataDirectoryFile(dataFileDir.getRoot());
brokerService.setPersistenceAdapter(jdbc);
brokerService.setDeleteAllMessagesOnStartup(true);
PolicyMap policyMap = new PolicyMap();
PolicyEntry defaultEntry = new PolicyEntry();
defaultEntry.setExpireMessagesPeriod(5000);
defaultEntry.setMaxExpirePageSize(expireSize);
policyMap.setDefaultEntry(defaultEntry);
brokerService.setDestinationPolicy(policyMap);
brokerService.start();
}
@After
public void stop() throws Exception {
if (brokerService != null) {
brokerService.stop();
brokerService.waitUntilStopped();
}
}
@Test
public void testMaxExpirePageSize() throws Exception {
final ActiveMQTopic topic = new ActiveMQTopic("test.topic");
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("vm://localhost");
factory.setClientID("clientId");;
Connection conn = factory.createConnection();
conn.start();
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
TopicSubscriber sub = sess.createDurableSubscriber(topic, "sub1");
sub.close();
MessageProducer producer = sess.createProducer(topic);
producer.setTimeToLive(1000);
for (int i = 0; i < 50; i++) {
producer.send(sess.createTextMessage("test message: " + i));
}
//There should be exactly 5 messages expired because the limit was hit and it stopped
//The expire messages period is 5 seconds which should give enough time for this assertion
//to pass before expiring more messages
assertTrue(Wait.waitFor(new Condition() {
@Override
public boolean isSatisified() throws Exception {
long expired = brokerService.getDestination(topic).getDestinationStatistics().getExpired().getCount();
return expired == expireSize && hasSpaceCalled.get();
}
}, 15000, 1000));
}
}