Added "recovery-interval" attribute to <jms:listener-container>
Issue: SPR-10711
This commit is contained in:
parent
4c0da5867a
commit
bb18f81b50
|
|
@ -49,6 +49,8 @@ class JmsListenerContainerParser extends AbstractListenerContainerParser {
|
||||||
|
|
||||||
private static final String RECEIVE_TIMEOUT_ATTRIBUTE = "receive-timeout";
|
private static final String RECEIVE_TIMEOUT_ATTRIBUTE = "receive-timeout";
|
||||||
|
|
||||||
|
private static final String RECOVERY_INTERVAL_ATTRIBUTE = "recovery-interval";
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected BeanDefinition parseContainer(Element listenerEle, Element containerEle, ParserContext parserContext) {
|
protected BeanDefinition parseContainer(Element listenerEle, Element containerEle, ParserContext parserContext) {
|
||||||
|
|
@ -160,6 +162,13 @@ class JmsListenerContainerParser extends AbstractListenerContainerParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String recoveryInterval = containerEle.getAttribute(RECOVERY_INTERVAL_ATTRIBUTE);
|
||||||
|
if (StringUtils.hasText(recoveryInterval)) {
|
||||||
|
if (containerType.startsWith("default")) {
|
||||||
|
containerDef.getPropertyValues().add("recoveryInterval", recoveryInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String phase = containerEle.getAttribute(PHASE_ATTRIBUTE);
|
String phase = containerEle.getAttribute(PHASE_ATTRIBUTE);
|
||||||
if (StringUtils.hasText(phase)) {
|
if (StringUtils.hasText(phase)) {
|
||||||
containerDef.getPropertyValues().add("phase", phase);
|
containerDef.getPropertyValues().add("phase", phase);
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,14 @@
|
||||||
]]></xsd:documentation>
|
]]></xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
</xsd:attribute>
|
</xsd:attribute>
|
||||||
|
<xsd:attribute name="recovery-interval" type="xsd:string">
|
||||||
|
<xsd:annotation>
|
||||||
|
<xsd:documentation><![CDATA[
|
||||||
|
Specify the interval between recovery attempts, in milliseconds.
|
||||||
|
The default is 5000 ms, that is, 5 seconds.
|
||||||
|
]]></xsd:documentation>
|
||||||
|
</xsd:annotation>
|
||||||
|
</xsd:attribute>
|
||||||
<xsd:attribute name="phase" type="xsd:string">
|
<xsd:attribute name="phase" type="xsd:string">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
<xsd:documentation><![CDATA[
|
<xsd:documentation><![CDATA[
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,17 @@ public class JmsNamespaceHandlerTests {
|
||||||
assertSame(message3, testBean3.message);
|
assertSame(message3, testBean3.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRecoveryInterval() {
|
||||||
|
long recoveryInterval1 = getRecoveryInterval("listener1");
|
||||||
|
long recoveryInterval2 = getRecoveryInterval("listener2");
|
||||||
|
long recoveryInterval3 = getRecoveryInterval(DefaultMessageListenerContainer.class.getName() + "#0");
|
||||||
|
|
||||||
|
assertEquals(1000L, recoveryInterval1);
|
||||||
|
assertEquals(1000L, recoveryInterval2);
|
||||||
|
assertEquals(DefaultMessageListenerContainer.DEFAULT_RECOVERY_INTERVAL, recoveryInterval3);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testErrorHandlers() {
|
public void testErrorHandlers() {
|
||||||
ErrorHandler expected = this.context.getBean("testErrorHandler", ErrorHandler.class);
|
ErrorHandler expected = this.context.getBean("testErrorHandler", ErrorHandler.class);
|
||||||
|
|
@ -164,24 +175,6 @@ public class JmsNamespaceHandlerTests {
|
||||||
assertEquals(Integer.MAX_VALUE, defaultPhase);
|
assertEquals(Integer.MAX_VALUE, defaultPhase);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MessageListener getListener(String containerBeanName) {
|
|
||||||
DefaultMessageListenerContainer container = this.context.getBean(containerBeanName, DefaultMessageListenerContainer.class);
|
|
||||||
return (MessageListener) container.getMessageListener();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ErrorHandler getErrorHandler(String containerBeanName) {
|
|
||||||
DefaultMessageListenerContainer container = this.context.getBean(containerBeanName, DefaultMessageListenerContainer.class);
|
|
||||||
return (ErrorHandler) new DirectFieldAccessor(container).getPropertyValue("errorHandler");
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPhase(String containerBeanName) {
|
|
||||||
Object container = this.context.getBean(containerBeanName);
|
|
||||||
if (!(container instanceof Phased)) {
|
|
||||||
throw new IllegalStateException("Container '" + containerBeanName + "' does not implement Phased.");
|
|
||||||
}
|
|
||||||
return ((Phased) container).getPhase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testComponentRegistration() {
|
public void testComponentRegistration() {
|
||||||
assertTrue("Parser should have registered a component named 'listener1'", context.containsComponentDefinition("listener1"));
|
assertTrue("Parser should have registered a component named 'listener1'", context.containsComponentDefinition("listener1"));
|
||||||
|
|
@ -203,6 +196,7 @@ public class JmsNamespaceHandlerTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void validateComponentDefinition(ComponentDefinition compDef) {
|
private void validateComponentDefinition(ComponentDefinition compDef) {
|
||||||
BeanDefinition[] beanDefs = compDef.getBeanDefinitions();
|
BeanDefinition[] beanDefs = compDef.getBeanDefinitions();
|
||||||
for (BeanDefinition beanDef : beanDefs) {
|
for (BeanDefinition beanDef : beanDefs) {
|
||||||
|
|
@ -210,6 +204,30 @@ public class JmsNamespaceHandlerTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MessageListener getListener(String containerBeanName) {
|
||||||
|
DefaultMessageListenerContainer container = this.context.getBean(containerBeanName, DefaultMessageListenerContainer.class);
|
||||||
|
return (MessageListener) container.getMessageListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ErrorHandler getErrorHandler(String containerBeanName) {
|
||||||
|
DefaultMessageListenerContainer container = this.context.getBean(containerBeanName, DefaultMessageListenerContainer.class);
|
||||||
|
return (ErrorHandler) new DirectFieldAccessor(container).getPropertyValue("errorHandler");
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getRecoveryInterval(String containerBeanName) {
|
||||||
|
DefaultMessageListenerContainer container = this.context.getBean(containerBeanName, DefaultMessageListenerContainer.class);
|
||||||
|
Long recoveryInterval = (Long) new DirectFieldAccessor(container).getPropertyValue("recoveryInterval");
|
||||||
|
return recoveryInterval.longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getPhase(String containerBeanName) {
|
||||||
|
Object container = this.context.getBean(containerBeanName);
|
||||||
|
if (!(container instanceof Phased)) {
|
||||||
|
throw new IllegalStateException("Container '" + containerBeanName + "' does not implement Phased.");
|
||||||
|
}
|
||||||
|
return ((Phased) container).getPhase();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class TestMessageListener implements MessageListener {
|
public static class TestMessageListener implements MessageListener {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:jms="http://www.springframework.org/schema/jms"
|
xmlns:jms="http://www.springframework.org/schema/jms"
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.1.xsd">
|
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-4.0.xsd">
|
||||||
|
|
||||||
<jms:listener-container connection-factory="testConnectionFactory" task-executor="testTaskExecutor"
|
<jms:listener-container connection-factory="testConnectionFactory" task-executor="testTaskExecutor"
|
||||||
destination-resolver="testDestinationResolver" message-converter="testMessageConverter"
|
destination-resolver="testDestinationResolver" message-converter="testMessageConverter"
|
||||||
transaction-manager="testTransactionManager" error-handler="testErrorHandler"
|
transaction-manager="testTransactionManager" error-handler="testErrorHandler"
|
||||||
concurrency="1-2" prefetch="50" receive-timeout="100" phase="99">
|
concurrency="1-2" prefetch="50" receive-timeout="100" recovery-interval="1000" phase="99">
|
||||||
<jms:listener id="listener1" destination="testDestination" ref="testBean1" method="setName"/>
|
<jms:listener id="listener1" destination="testDestination" ref="testBean1" method="setName"/>
|
||||||
<jms:listener id="listener2" destination="testDestination" ref="testBean2" method="setName" response-destination="responseDestination"/>
|
<jms:listener id="listener2" destination="testDestination" ref="testBean2" method="setName" response-destination="responseDestination"/>
|
||||||
</jms:listener-container>
|
</jms:listener-container>
|
||||||
|
|
|
||||||
|
|
@ -1086,6 +1086,16 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schem
|
||||||
<literal>'default'</literal>).</para></entry>
|
<literal>'default'</literal>).</para></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>container-class</entry>
|
||||||
|
|
||||||
|
<entry><para>A custom listener container implementation class
|
||||||
|
as fully qualified class name. Default is Spring's standard
|
||||||
|
<classname>DefaultMessageListenerContainer</classname> or
|
||||||
|
<classname>SimpleMessageListenerContainer</classname>,
|
||||||
|
according to the "container-type" attribute.</para></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>connection-factory</entry>
|
<entry>connection-factory</entry>
|
||||||
|
|
||||||
|
|
@ -1121,6 +1131,15 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schem
|
||||||
<classname>SimpleMessageConverter</classname>.</para></entry>
|
<classname>SimpleMessageConverter</classname>.</para></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>error-handler</entry>
|
||||||
|
|
||||||
|
<entry><para>A reference to an
|
||||||
|
<interfacename>ErrorHandler</interfacename> strategy for handling
|
||||||
|
any uncaught Exceptions that may occur during the execution of the
|
||||||
|
<interfacename>MessageListener</interfacename>.</para></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>destination-type</entry>
|
<entry>destination-type</entry>
|
||||||
|
|
||||||
|
|
@ -1195,6 +1214,32 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schem
|
||||||
session. Note that raising this number might lead to starvation of
|
session. Note that raising this number might lead to starvation of
|
||||||
concurrent consumers!</para></entry>
|
concurrent consumers!</para></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>receive-timeout</entry>
|
||||||
|
|
||||||
|
<entry><para>The timeout to use for receive calls (in milliseconds).
|
||||||
|
The default is <literal>1000</literal> ms (1 sec); <literal>-1</literal>
|
||||||
|
indicates no timeout at all.</para></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>recovery-interval</entry>
|
||||||
|
|
||||||
|
<entry><para>Specify the interval between recovery attempts, in
|
||||||
|
milliseconds. The default is <literal>5000</literal> ms, that is,
|
||||||
|
5 seconds.</para></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>phase</entry>
|
||||||
|
|
||||||
|
<entry><para>The lifecycle phase within which this container should
|
||||||
|
start and stop. The lower the value the earlier this container will
|
||||||
|
start and the later it will stop. The default is
|
||||||
|
<literal>Integer.MAX_VALUE</literal> meaning the container will start
|
||||||
|
as late as possible and stop as soon as possible.</para></entry>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue