Revised SingleConnectionFactory for individual proxies with ExceptionListener and start/stop state
Issue: SPR-10397
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,16 +46,16 @@ public class SingleConnectionFactoryTests {
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(con);
|
||||
Connection con1 = scf.createConnection();
|
||||
con1.start();
|
||||
con1.stop(); // should be ignored
|
||||
con1.close(); // should be ignored
|
||||
con1.stop();
|
||||
con1.close();
|
||||
Connection con2 = scf.createConnection();
|
||||
con2.start(); // should be ignored
|
||||
con2.stop(); // should be ignored
|
||||
con2.close(); // should be ignored
|
||||
con2.start();
|
||||
con2.stop();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(con).start();
|
||||
verify(con).stop();
|
||||
verify(con, times(2)).start();
|
||||
verify(con, times(2)).stop();
|
||||
verify(con).close();
|
||||
verifyNoMoreInteractions(con);
|
||||
}
|
||||
@@ -67,16 +67,16 @@ public class SingleConnectionFactoryTests {
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(con);
|
||||
QueueConnection con1 = scf.createQueueConnection();
|
||||
con1.start();
|
||||
con1.stop(); // should be ignored
|
||||
con1.close(); // should be ignored
|
||||
con1.stop();
|
||||
con1.close();
|
||||
QueueConnection con2 = scf.createQueueConnection();
|
||||
con2.start();
|
||||
con2.stop(); // should be ignored
|
||||
con2.close(); // should be ignored
|
||||
con2.stop();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(con).start();
|
||||
verify(con).stop();
|
||||
verify(con, times(2)).start();
|
||||
verify(con, times(2)).stop();
|
||||
verify(con).close();
|
||||
verifyNoMoreInteractions(con);
|
||||
}
|
||||
@@ -88,16 +88,16 @@ public class SingleConnectionFactoryTests {
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(con);
|
||||
TopicConnection con1 = scf.createTopicConnection();
|
||||
con1.start();
|
||||
con1.stop(); // should be ignored
|
||||
con1.close(); // should be ignored
|
||||
con1.stop();
|
||||
con1.close();
|
||||
TopicConnection con2 = scf.createTopicConnection();
|
||||
con2.start();
|
||||
con2.stop(); // should be ignored
|
||||
con2.close(); // should be ignored
|
||||
con2.stop();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(con).start();
|
||||
verify(con).stop();
|
||||
verify(con, times(2)).start();
|
||||
verify(con, times(2)).stop();
|
||||
verify(con).close();
|
||||
verifyNoMoreInteractions(con);
|
||||
}
|
||||
@@ -111,11 +111,11 @@ public class SingleConnectionFactoryTests {
|
||||
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(cf);
|
||||
Connection con1 = scf.createConnection();
|
||||
con1.start();
|
||||
con1.close(); // should be ignored
|
||||
Connection con2 = scf.createConnection();
|
||||
con1.start();
|
||||
con2.start();
|
||||
con2.close(); // should be ignored
|
||||
con1.close();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(con).start();
|
||||
@@ -133,11 +133,11 @@ public class SingleConnectionFactoryTests {
|
||||
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(cf);
|
||||
Connection con1 = scf.createConnection();
|
||||
con1.start();
|
||||
con1.close(); // should be ignored
|
||||
Connection con2 = scf.createConnection();
|
||||
con1.start();
|
||||
con2.start();
|
||||
con2.close(); // should be ignored
|
||||
con1.close();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(con).start();
|
||||
@@ -155,11 +155,11 @@ public class SingleConnectionFactoryTests {
|
||||
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(cf);
|
||||
Connection con1 = scf.createQueueConnection();
|
||||
con1.start();
|
||||
con1.close(); // should be ignored
|
||||
Connection con2 = scf.createQueueConnection();
|
||||
con1.start();
|
||||
con2.start();
|
||||
con2.close(); // should be ignored
|
||||
con1.close();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(con).start();
|
||||
@@ -177,11 +177,11 @@ public class SingleConnectionFactoryTests {
|
||||
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(cf);
|
||||
Connection con1 = scf.createConnection();
|
||||
con1.start();
|
||||
con1.close(); // should be ignored
|
||||
Connection con2 = scf.createConnection();
|
||||
con1.start();
|
||||
con2.start();
|
||||
con2.close(); // should be ignored
|
||||
con1.close();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(con).start();
|
||||
@@ -199,11 +199,11 @@ public class SingleConnectionFactoryTests {
|
||||
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(cf);
|
||||
Connection con1 = scf.createTopicConnection();
|
||||
con1.start();
|
||||
con1.close(); // should be ignored
|
||||
Connection con2 = scf.createTopicConnection();
|
||||
con1.start();
|
||||
con2.start();
|
||||
con2.close(); // should be ignored
|
||||
con1.close();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(con).start();
|
||||
@@ -212,21 +212,52 @@ public class SingleConnectionFactoryTests {
|
||||
verifyNoMoreInteractions(con);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithConnectionAggregatedStartStop() throws JMSException {
|
||||
Connection con = mock(Connection.class);
|
||||
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(con);
|
||||
Connection con1 = scf.createConnection();
|
||||
con1.start();
|
||||
verify(con).start();
|
||||
con1.stop();
|
||||
verify(con).stop();
|
||||
Connection con2 = scf.createConnection();
|
||||
con2.start();
|
||||
verify(con, times(2)).start();
|
||||
con2.stop();
|
||||
verify(con, times(2)).stop();
|
||||
con2.start();
|
||||
verify(con, times(3)).start();
|
||||
con1.start();
|
||||
con2.stop();
|
||||
con1.stop();
|
||||
verify(con, times(3)).stop();
|
||||
con1.start();
|
||||
verify(con, times(4)).start();
|
||||
con1.close();
|
||||
verify(con, times(4)).stop();
|
||||
con2.close();
|
||||
scf.destroy();
|
||||
verify(con).close();
|
||||
|
||||
verifyNoMoreInteractions(con);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithConnectionFactoryAndClientId() throws JMSException {
|
||||
ConnectionFactory cf = mock(ConnectionFactory.class);
|
||||
Connection con = mock(Connection.class);
|
||||
|
||||
given(cf.createConnection()).willReturn(con);
|
||||
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(cf);
|
||||
scf.setClientId("myId");
|
||||
Connection con1 = scf.createConnection();
|
||||
con1.start();
|
||||
con1.close(); // should be ignored
|
||||
Connection con2 = scf.createConnection();
|
||||
con1.start();
|
||||
con2.start();
|
||||
con2.close(); // should be ignored
|
||||
con1.close();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(con).setClientID("myId");
|
||||
@@ -250,17 +281,17 @@ public class SingleConnectionFactoryTests {
|
||||
Connection con1 = scf.createConnection();
|
||||
assertEquals(listener, con1.getExceptionListener());
|
||||
con1.start();
|
||||
con1.stop(); // should be ignored
|
||||
con1.close(); // should be ignored
|
||||
con1.stop();
|
||||
con1.close();
|
||||
Connection con2 = scf.createConnection();
|
||||
con2.start();
|
||||
con2.stop(); // should be ignored
|
||||
con2.close(); // should be ignored
|
||||
con2.stop();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(con).setExceptionListener(listener);
|
||||
verify(con).start();
|
||||
verify(con).stop();
|
||||
verify(con, times(2)).start();
|
||||
verify(con, times(2)).stop();
|
||||
verify(con).close();
|
||||
}
|
||||
|
||||
@@ -268,7 +299,6 @@ public class SingleConnectionFactoryTests {
|
||||
public void testWithConnectionFactoryAndReconnectOnException() throws JMSException {
|
||||
ConnectionFactory cf = mock(ConnectionFactory.class);
|
||||
TestConnection con = new TestConnection();
|
||||
|
||||
given(cf.createConnection()).willReturn(con);
|
||||
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(cf);
|
||||
@@ -289,7 +319,6 @@ public class SingleConnectionFactoryTests {
|
||||
public void testWithConnectionFactoryAndExceptionListenerAndReconnectOnException() throws JMSException {
|
||||
ConnectionFactory cf = mock(ConnectionFactory.class);
|
||||
TestConnection con = new TestConnection();
|
||||
|
||||
given(cf.createConnection()).willReturn(con);
|
||||
|
||||
TestExceptionListener listener = new TestExceptionListener();
|
||||
@@ -309,6 +338,78 @@ public class SingleConnectionFactoryTests {
|
||||
assertEquals(1, listener.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithConnectionFactoryAndLocalExceptionListenerWithCleanup() throws JMSException {
|
||||
ConnectionFactory cf = mock(ConnectionFactory.class);
|
||||
TestConnection con = new TestConnection();
|
||||
given(cf.createConnection()).willReturn(con);
|
||||
|
||||
TestExceptionListener listener0 = new TestExceptionListener();
|
||||
TestExceptionListener listener1 = new TestExceptionListener();
|
||||
TestExceptionListener listener2 = new TestExceptionListener();
|
||||
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(cf) {
|
||||
@Override
|
||||
public void onException(JMSException ex) {
|
||||
// no-op
|
||||
}
|
||||
};
|
||||
scf.setReconnectOnException(true);
|
||||
scf.setExceptionListener(listener0);
|
||||
Connection con1 = scf.createConnection();
|
||||
con1.setExceptionListener(listener1);
|
||||
assertSame(listener1, con1.getExceptionListener());
|
||||
Connection con2 = scf.createConnection();
|
||||
con2.setExceptionListener(listener2);
|
||||
assertSame(listener2, con2.getExceptionListener());
|
||||
con.getExceptionListener().onException(new JMSException(""));
|
||||
con2.close();
|
||||
con.getExceptionListener().onException(new JMSException(""));
|
||||
con1.close();
|
||||
con.getExceptionListener().onException(new JMSException(""));
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
assertEquals(0, con.getStartCount());
|
||||
assertEquals(1, con.getCloseCount());
|
||||
assertEquals(3, listener0.getCount());
|
||||
assertEquals(2, listener1.getCount());
|
||||
assertEquals(1, listener2.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithConnectionFactoryAndLocalExceptionListenerWithReconnect() throws JMSException {
|
||||
ConnectionFactory cf = mock(ConnectionFactory.class);
|
||||
TestConnection con = new TestConnection();
|
||||
given(cf.createConnection()).willReturn(con);
|
||||
|
||||
TestExceptionListener listener0 = new TestExceptionListener();
|
||||
TestExceptionListener listener1 = new TestExceptionListener();
|
||||
TestExceptionListener listener2 = new TestExceptionListener();
|
||||
|
||||
SingleConnectionFactory scf = new SingleConnectionFactory(cf);
|
||||
scf.setReconnectOnException(true);
|
||||
scf.setExceptionListener(listener0);
|
||||
Connection con1 = scf.createConnection();
|
||||
con1.setExceptionListener(listener1);
|
||||
assertSame(listener1, con1.getExceptionListener());
|
||||
con1.start();
|
||||
Connection con2 = scf.createConnection();
|
||||
con2.setExceptionListener(listener2);
|
||||
assertSame(listener2, con2.getExceptionListener());
|
||||
con.getExceptionListener().onException(new JMSException(""));
|
||||
con2.close();
|
||||
con1.getMetaData();
|
||||
con.getExceptionListener().onException(new JMSException(""));
|
||||
con1.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
assertEquals(2, con.getStartCount());
|
||||
assertEquals(2, con.getCloseCount());
|
||||
assertEquals(2, listener0.getCount());
|
||||
assertEquals(2, listener1.getCount());
|
||||
assertEquals(1, listener2.getCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCachingConnectionFactory() throws JMSException {
|
||||
ConnectionFactory cf = mock(ConnectionFactory.class);
|
||||
@@ -328,17 +429,17 @@ public class SingleConnectionFactoryTests {
|
||||
session1.getTransacted();
|
||||
session1.close(); // should lead to rollback
|
||||
session1 = con1.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
session1.close(); // should be ignored
|
||||
session1.close();
|
||||
con1.start();
|
||||
con1.close(); // should be ignored
|
||||
Connection con2 = scf.createConnection();
|
||||
Session session2 = con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
session2.close(); // should be ignored
|
||||
session2.close();
|
||||
session2 = con2.createSession(true, Session.AUTO_ACKNOWLEDGE);
|
||||
session2.commit();
|
||||
session2.close(); // should be ignored
|
||||
session2.close();
|
||||
con2.start();
|
||||
con2.close(); // should be ignored
|
||||
con1.close();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(txSession).commit();
|
||||
@@ -366,19 +467,19 @@ public class SingleConnectionFactoryTests {
|
||||
Connection con1 = scf.createQueueConnection();
|
||||
Session session1 = con1.createSession(true, Session.AUTO_ACKNOWLEDGE);
|
||||
session1.rollback();
|
||||
session1.close(); // should be ignored
|
||||
session1.close();
|
||||
session1 = con1.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
session1.close(); // should be ignored
|
||||
session1.close();
|
||||
con1.start();
|
||||
con1.close(); // should be ignored
|
||||
QueueConnection con2 = scf.createQueueConnection();
|
||||
Session session2 = con2.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
session2.close(); // should be ignored
|
||||
session2.close();
|
||||
session2 = con2.createSession(true, Session.AUTO_ACKNOWLEDGE);
|
||||
session2.getTransacted();
|
||||
session2.close(); // should lead to rollback
|
||||
con2.start();
|
||||
con2.close(); // should be ignored
|
||||
con1.close();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(txSession).rollback();
|
||||
@@ -408,17 +509,17 @@ public class SingleConnectionFactoryTests {
|
||||
session1.getTransacted();
|
||||
session1.close(); // should lead to rollback
|
||||
session1 = con1.createSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
session1.close(); // should be ignored
|
||||
session1.close();
|
||||
con1.start();
|
||||
con1.close(); // should be ignored
|
||||
TopicConnection con2 = scf.createTopicConnection();
|
||||
Session session2 = con2.createTopicSession(false, Session.CLIENT_ACKNOWLEDGE);
|
||||
session2.close(); // should be ignored
|
||||
session2.close();
|
||||
session2 = con2.createSession(true, Session.AUTO_ACKNOWLEDGE);
|
||||
session2.getTransacted();
|
||||
session2.close(); // should be ignored
|
||||
session2.close();
|
||||
con2.start();
|
||||
con2.close(); // should be ignored
|
||||
con1.close();
|
||||
con2.close();
|
||||
scf.destroy(); // should trigger actual close
|
||||
|
||||
verify(txSession).close();
|
||||
|
||||
Reference in New Issue
Block a user