package com.googlecode.mycontainer.jms;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.util.ArrayList;
import java.util.List;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQMessageConsumer;
import org.apache.activemq.RedeliveryPolicy;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.googlecode.mycontainer.ejb.SessionInterceptorDeployer;
import com.googlecode.mycontainer.ejb.StatelessDeployer;
import com.googlecode.mycontainer.jta.MyTransactionManagerDeployer;
import com.googlecode.mycontainer.kernel.ShutdownCommand;
import com.googlecode.mycontainer.kernel.boot.ContainerBuilder;
import com.googlecode.mycontainer.kernel.naming.MyNameParser;
/**
* There is a bug with redelivery (MessageListener, not transacted and
* AUTO_ACKNOWLEDGE):
* <url>https://issues.apache.org/activemq/browse/AMQ-906</url>
*
* I will wait for activemq 5.4 release to final solution.
*
* You can do a <code>consumer.rollback()</code> like the
* <code>MyListener.onMessage</code> as a workaround.
*
*
*/
public class JMSDeployerErrorTest {
private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(JMSDeployerErrorTest.class);
private class MyListener implements MessageListener {
private ActiveMQConnection conn;
private Session session;
private MessageConsumer consumer;
private final List<String> msgs = new ArrayList<String>();
private final Object lock = new Object();
public void onMessage(Message message) {
TextMessage text = (TextMessage) message;
try {
synchronized (lock) {
String t = text.getText();
LOG.info("Message received: " + t + " " + message.getJMSRedelivered());
boolean error = t.startsWith("Error");
if (error) {
t = t.split("\\:", 2)[1];
}
this.msgs.add(t);
lock.notifyAll();
if (error) {
ActiveMQMessageConsumer amc = (ActiveMQMessageConsumer) consumer;
amc.rollback();
}
}
} catch (JMSException e) {
throw new RuntimeException(e);
}
}
public String nextMessage() throws Exception {
return nextMessage(100l);
}
public String nextMessage(long time) throws Exception {
synchronized (lock) {
if (this.msgs.isEmpty()) {
lock.wait(time);
}
if (this.msgs.isEmpty()) {
return null;
}
String ret = this.msgs.remove(0);
return ret;
}
}
public void start(ConnectionFactory connectionFactory, Queue queue) throws Exception {
conn = (ActiveMQConnection) connectionFactory.createConnection();
RedeliveryPolicy policy = conn.getRedeliveryPolicy();
policy.setMaximumRedeliveries(3);
policy.setInitialRedeliveryDelay(5);
session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
consumer = session.createConsumer(queue);
consumer.setMessageListener(this);
conn.start();
}
public void close() {
c(consumer);
c(session);
c(conn);
}
};
private InitialContext ctx;
private Queue queue;
private ConnectionFactory connectionFactory;
@Before
public void bootMycontainer() throws Exception {
ContainerBuilder builder = new ContainerBuilder();
SessionInterceptorDeployer sessionInterceptorDeployer = builder.createDeployer(SessionInterceptorDeployer.class);
sessionInterceptorDeployer.deploy();
builder.createDeployer(MyTransactionManagerDeployer.class).setName("TransactionManager").deploy();
JMSDeployer jmsDeployer = builder.createDeployer(JMSDeployer.class);
jmsDeployer.createQueue("queueRaoni");
jmsDeployer.createTopic("topicRaoni");
jmsDeployer.deploy();
StatelessDeployer statelessDeployer = builder.createDeployer(StatelessDeployer.class);
statelessDeployer.deploy(TesterServiceBean.class);
ctx = builder.getContext();
connectionFactory = (QueueConnectionFactory) ctx.lookup(MyNameParser.parseClassName("resource", ConnectionFactory.class));
queue = (Queue) ctx.lookup("queue/queueRaoni");
}
@Test
public void testCreateProducer() throws Exception {
MyListener listener = new MyListener();
listener.start(connectionFactory, queue);
send("My message");
assertEquals("My message", listener.nextMessage());
send("My message2");
assertEquals("My message2", listener.nextMessage());
assertNull(listener.nextMessage());
send("Error: My message3");
assertEquals(" My message3", listener.nextMessage());
assertEquals(" My message3", listener.nextMessage());
assertEquals(" My message3", listener.nextMessage());
assertEquals(" My message3", listener.nextMessage());
assertNull(listener.nextMessage());
listener.close();
}
private void send(String msg) {
Connection connection = null;
Session session = null;
MessageConsumer consumer1 = null;
MessageProducer sender = null;
try {
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
sender = session.createProducer(queue);
TextMessage txtMessage = session.createTextMessage(msg);
sender.send(txtMessage);
} catch (JMSException e) {
throw new RuntimeException(e);
} finally {
c(consumer1);
c(sender);
c(session);
c(connection);
}
}
private void c(Connection conn) {
try {
if (conn != null) {
conn.stop();
conn.close();
}
} catch (JMSException e) {
LOG.error("Error closing jms connection", e);
}
}
private void c(MessageConsumer o) {
try {
if (o != null) {
o.close();
}
} catch (JMSException e) {
LOG.error("Error closing jms session", e);
}
}
private void c(MessageProducer o) {
try {
if (o != null) {
o.close();
}
} catch (JMSException e) {
LOG.error("Error closing jms session", e);
}
}
private void c(Session session) {
try {
if (session != null) {
session.close();
}
} catch (JMSException e) {
LOG.error("Error closing jms session", e);
}
}
@After
public void shutdown() {
try {
ShutdownCommand shutdown = new ShutdownCommand();
shutdown.setContext(new InitialContext());
shutdown.shutdown();
} catch (Exception e) {
LOG.error("Error shutdown", e);
}
}
}