I've inherited a Spring Integration project that incorporates Spring Retry. I'm not sure it has ever been tested out, and there is no separate tests for it. So I'm trying to exercise it with a simple scenario.
By mocking the RestTemplate exchange
method, I'd like to be able to test the retry logic. I can get the exception I want thrown to occur, but it only happens once - no retry is taking place.
The XML for the retry advice is here(retry-advice-context.xml):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="retryAdvice" class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice" >
<property name="retryTemplate">
<bean class="org.springframework.retry.support.RetryTemplate">
<property name="backOffPolicy">
<bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
<property name="initialInterval" value="${retry.initialInterval}"/>
<property name="maxInterval" value="${retry.maxInterval}"/>
<property name="multiplier" value="${retry.multiplier}"/>
</bean>
</property>
<property name="retryPolicy">
<bean class="com.reachlocal.mediapublishing.shim.integration.retry.CustomRetryPolicy">
<constructor-arg name="maxAttempts" value="${retry.maxAttempts}" />
<constructor-arg name="retryableExceptions" ref="retryableExceptions" />
</bean>
</property>
</bean>
</property>
<property name="recoveryCallback">
<bean class="org.springframework.integration.handler.advice.ErrorMessageSendingRecoverer">
<constructor-arg ref="errorChannel" />
</bean>
</property>
</bean>
<util:map id="retryableExceptions" map-class="java.util.HashMap" >
<entry key="java.net.SocketException" value="true" />
<entry key="com.examplel.ConnectionException" value="true" />
<entry key="com.example.CustomException" value="true" />
</util:map>
</beans>
Here is a chunk of an SI processing file:
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
<import resource="retry-advice-context.xml"/>
<int:channel id="channel1">
</int:channel>
<int:header-value-router id="commandTypeRouter" input-channel="commandChannel" <---DEFINED IN MASTER FILE
header-name="commandType" resolution-required="true">
<int:mapping value="COMMAND_1" channel="channel1"/>
</int:header-value-router>
<int:chain id="command1Chain" input-channel="channel1" output-channel="commandProcessed">
<int:header-enricher>
<int:error-channel ref="errorChannel" />
</int:header-enricher>
<int:service-activator ref="eventDataWriter" method = "addEventStart"/>
<int:service-activator ref="accountProcessor" method="processAccount">
<int:request-handler-advice-chain><ref bean="retryAdvice" /></int:request-handler-advice-chain>
</int:service-activator>
</int:chain>
</beans>
So the retry bean, retryAdvice
, is a part of the different chains. There is a lot more to the chains, so I only want to be able to check the retry logic from the service layer. There are no Retry annotations anywhere in the code (don't know if they are needed).
A couple of questions:
- Can I test the retry feature from the service layer or do I need to execute the entire chain?
- Is there anything missing (annotations, other XML) that the retry mechanism requires?
BTW, this is using SI 4.1.3.
Thanks.
UPDATE 1:
Managed to get a Gary's project running in my environment. After that I added in the retry-advice-context.xml
file into the main SI xml. I changed the Map to only have RuntimeException
in it. The log statements showed ExponentialBackoffPolicy
statements. I was also getting the RetryTemplate
debug log statements.
With some more understanding I translated what was there to the real code I'm working with and had more success. I'm getting the log statement that my exception occurred and will be retried up to 3 times.
Unfortunately what I get is:
17:29:26.154 DEBUG [task-scheduler-2][org.springframework.retry.support.RetryTemplate] Checking for rethrow: count=1
17:29:26.155 DEBUG [task-scheduler-2][org.springframework.retry.support.RetryTemplate] Retry failed last attempt: count=1
So it initially knows that it's supposed to retry up to 3 times. But then it states that it's made its last attempt after 1 retry.
In Gary's working code the debug statements will show Retry: count=2
etc... for the next successive try.
There is a sleep
statement in the Spock test code during the time the retries should be taking place. I both lengthened and shortened the time without any change.
Going to continue to try and debug through the retry code to see why it stops on the 1st retry.