RabbitMQ message still retries after throwing AmqpRejectAndDontRequeueException - spring-boot

I have a simple Spring Boot application where I have the following settings for RabbitMQ (spring-boot-starter-amqp version is 2.7.0):
spring:
rabbitmq:
host: localhost
port: 5672
virtual-host: my_host
username: admin
password: password
template:
retry:
enabled: true
initial-interval: 3s
max-interval: 10s
multiplier: 2
max-attempts: 3
listener:
simple:
retry:
enabled: true
initial-interval: 3s
max-interval: 10s
multiplier: 2
max-attempts: 3
A SimpleRabbitListenerContainerFactory is configured with a MessagePostProcessor:
#Bean
public SimpleRabbitListenerContainerFactory myInterceptContainerFactory(final SimpleRabbitListenerContainerFactoryConfigurer configurer,
final ConnectionFactory connectionFactory,
final MyMessagePostProcessor myMessagePostProcessor) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory() {
#Override
protected void initializeContainer(SimpleMessageListenerContainer instance, RabbitListenerEndpoint endpoint) {
instance.setAfterReceivePostProcessors(myMessagePostProcessor);
super.initializeContainer(instance, endpoint);
}
};
((CachingConnectionFactory) connectionFactory).setRequestedHeartBeat(60);
configurer.configure(factory, connectionFactory);
return factory;
}
MessagePostProcessor is very simple, if the version is wrong in the header, it throws an AmqpRejectAndDontRequeueException:
#Component
public class MyMessagePostProcessor implements MessagePostProcessor {
private static final Logger LOGGER = LogManager.getLogger(MyMessagePostProcessor.class);
#Override
public Message postProcessMessage(Message message) throws AmqpException {
if (!"1.0".equalsIgnoreCase(message.getMessageProperties().getHeader("version"))) {
LOGGER.error("wrong version");
throw new AmqpRejectAndDontRequeueException("wrong version");
}
return message;
}
}
When I send a message with a wrong version, it works properly based on the logs:
MyApp: 2022-07-05 15:49:33,675 ERROR [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] c.g.r.a.q.p.MyMessagePostProcessor:22 - wrong version
MyApp: 2022-07-05 15:49:33,676 WARN [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] o.s.a.r.l.ConditionalRejectingErrorHandler:169 - Execution of Rabbit message listener failed.
org.springframework.amqp.AmqpRejectAndDontRequeueException: wrong version
at com.my.app.queue.postprocess.MyMessagePostProcessor.postProcessMessage(MyMessagePostProcessor.java:23) ~[classes/:1.0.0]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1544) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1499) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:992) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:939) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:84) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1316) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1222) ~[spring-rabbit-2.4.5.jar:2.4.5]
at java.lang.Thread.run(Thread.java:833) ~[?:?]
My consumer is only doing one error log and immediately throws AmqpRejectAndDontRequeueException to see if the message goes into the deadletter queue without retry:
#Component
public class MyMessageConsumer {
private static final Logger LOGGER = LogManager.getLogger(MyMessageConsumer.class);
#RabbitListener(queues = "my.queue", containerFactory = "myInterceptContainerFactory")
public void consumerMessage() {
LOGGER.error("error in consuming message");
throw new AmqpRejectAndDontRequeueException("over");
}
}
But based on the logs it is clearly visible that it retries 3 times (because my error log is printed 3 times) and only after then the message is delivered into deadletter queue:
MyApp: 2022-07-05 15:50:32,182 ERROR [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] c.g.r.a.q.c.MyMessageConsumer:23 - error in consuming message
MyApp: 2022-07-05 15:50:46,603 ERROR [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] c.g.r.a.q.c.MyMessageConsumer:23 - error in consuming message
MyApp: 2022-07-05 15:50:52,617 ERROR [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] c.g.r.a.q.c.MyMessageConsumer:23 - error in consuming message
MyApp: 2022-07-05 15:50:52,618 WARN [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] o.s.a.r.r.RejectAndDontRequeueRecoverer:74 - Retries exhausted for message (Body:'[B#4060893b(byte[75])' MessageProperties [headers={version=1.0, requestor=MyApp}, contentLength=0, receivedDeliveryMode=NON_PERSISTENT, redelivered=false, receivedExchange=, receivedRoutingKey=my.queue, deliveryTag=2, consumerTag=amq.ctag-5Xx6EwwjVokRV6wD9xL8Og, consumerQueue=my.queue])
org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Listener method 'public void com.my.app.queue.consumer.MyMessageConsumer.retrieveNcid()' threw exception
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:271) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandlerAndProcessResult(MessagingMessageListenerAdapter.java:208) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:147) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1657) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1576) ~[spring-rabbit-2.4.5.jar:2.4.5]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.retry.interceptor.RetryOperationsInterceptor$1.doWithRetry(RetryOperationsInterceptor.java:97) ~[spring-retry-1.3.3.jar:?]
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329) ~[spring-retry-1.3.3.jar:?]
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:225) ~[spring-retry-1.3.3.jar:?]
at org.springframework.retry.interceptor.RetryOperationsInterceptor.invoke(RetryOperationsInterceptor.java:122) ~[spring-retry-1.3.3.jar:?]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.amqp.rabbit.listener.$Proxy187.invokeListener(Unknown Source) ~[?:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1564) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1555) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1499) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:992) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:939) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:84) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1316) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1222) ~[spring-rabbit-2.4.5.jar:2.4.5]
at java.lang.Thread.run(Thread.java:833) ~[?:?]
Caused by: org.springframework.amqp.AmqpRejectAndDontRequeueException: over
at com.my.app.queue.consumer.MyMessageConsumer.retrieveNcid(MyMessageConsumer.java:24) ~[classes/:1.0.0]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:169) ~[spring-messaging-5.3.20.jar:5.3.20]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:119) ~[spring-messaging-5.3.20.jar:5.3.20]
at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:75) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:262) ~[spring-rabbit-2.4.5.jar:2.4.5]
... 27 more
MyApp: 2022-07-05 15:50:52,620 WARN [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] o.s.a.r.l.ConditionalRejectingErrorHandler:169 - Execution of Rabbit message listener failed.
org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Retry Policy Exhausted
at org.springframework.amqp.rabbit.retry.RejectAndDontRequeueRecoverer.recover(RejectAndDontRequeueRecoverer.java:76) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.config.StatelessRetryOperationsInterceptorFactoryBean.recover(StatelessRetryOperationsInterceptorFactoryBean.java:77) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.retry.interceptor.RetryOperationsInterceptor$ItemRecovererCallback.recover(RetryOperationsInterceptor.java:157) ~[spring-retry-1.3.3.jar:?]
at org.springframework.retry.support.RetryTemplate.handleRetryExhausted(RetryTemplate.java:539) ~[spring-retry-1.3.3.jar:?]
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:387) ~[spring-retry-1.3.3.jar:?]
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:225) ~[spring-retry-1.3.3.jar:?]
at org.springframework.retry.interceptor.RetryOperationsInterceptor.invoke(RetryOperationsInterceptor.java:122) ~[spring-retry-1.3.3.jar:?]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.amqp.rabbit.listener.$Proxy187.invokeListener(Unknown Source) ~[?:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1564) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1555) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1499) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:992) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:939) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:84) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1316) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1222) ~[spring-rabbit-2.4.5.jar:2.4.5]
at java.lang.Thread.run(Thread.java:833) ~[?:?]
Caused by: org.springframework.amqp.AmqpRejectAndDontRequeueException
... 19 more
Caused by: org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Listener method 'public void com.my.app.queue.consumer.MyMessageConsumer.retrieveNcid()' threw exception
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:271) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandlerAndProcessResult(MessagingMessageListenerAdapter.java:208) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:147) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1657) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1576) ~[spring-rabbit-2.4.5.jar:2.4.5]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.retry.interceptor.RetryOperationsInterceptor$1.doWithRetry(RetryOperationsInterceptor.java:97) ~[spring-retry-1.3.3.jar:?]
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329) ~[spring-retry-1.3.3.jar:?]
... 14 more
Caused by: org.springframework.amqp.AmqpRejectAndDontRequeueException: over
at com.my.app.queue.consumer.MyMessageConsumer.retrieveNcid(MyMessageConsumer.java:24) ~[classes/:1.0.0]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:169) ~[spring-messaging-5.3.20.jar:5.3.20]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:119) ~[spring-messaging-5.3.20.jar:5.3.20]
at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:75) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:262) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandlerAndProcessResult(MessagingMessageListenerAdapter.java:208) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:147) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1657) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1576) ~[spring-rabbit-2.4.5.jar:2.4.5]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.20.jar:5.3.20]
at org.springframework.retry.interceptor.RetryOperationsInterceptor$1.doWithRetry(RetryOperationsInterceptor.java:97) ~[spring-retry-1.3.3.jar:?]
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329) ~[spring-retry-1.3.3.jar:?]
... 14 more
But I want to deliver the message into the deadletter queue without retrying it 3 times.
I guess there is something with ListenerExecutionFailedException: Retry Policy Exhausted, but I don't understand why my AmqpRejectAndDontRequeueException is wrapped in this exception, because my MessagePostProcessor doesn't throw ListenerExecutionFailedException, only the one which I throw in code.
What am I missing here?

As #Gary Russel suggested, I modified the retry policy as below:
#Bean
public RabbitRetryTemplateCustomizer customizeRetryPolicy(#Value("${spring.rabbitmq.listener.simple.retry.max-attempts}") int maxAttempts) {
SimpleRetryPolicy policy = new SimpleRetryPolicy(maxAttempts, Map.of(AmqpRejectAndDontRequeueException.class, false), true, true);
return (target, retryTemplate) -> retryTemplate.setRetryPolicy(policy);
}
And only configuring this new bean, everything works as expected!

The container knows nothing about the exception until retries are exhausted.
You would need to customize the retry policy to not retry for that exception.
This is currently not possible using application properties; you would need to configure the retry interceptor as a bean and inject it into the container factory.
If you need help with that, I can add an example.

Related

Why getting connection refused with elasticsearch 8 and springboot 3

I am trying to connect to elasticsearch 8 from my springboot 3 project floowing this official doc. But getting connection refused error without much details.
Here is my configuration
#Configuration
#Slf4j
#EnableElasticsearchRepositories(basePackages = "com....elastic")
public class ElasticConfig {
#Bean
public ClientConfiguration clientConfiguration() {
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("192.168.19.23:9200")
.usingSsl()
.withConnectTimeout(Duration.ofSeconds(5))
.withSocketTimeout(Duration.ofSeconds(3))
.withBasicAuth("elastic", "abc")
.build();
return clientConfiguration;
}
}
I have my SSL certificate in my jdk. The project runs properly but when it tries to save data on elasticsearch, it gets this error
org.springframework.dao.DataAccessResourceFailureException: Connection refused
at org.springframework.data.elasticsearch.client.elc.ElasticsearchExceptionTranslator.translateExceptionIfPossible(ElasticsearchExceptionTranslator.java:100)
at org.springframework.data.elasticsearch.client.elc.ElasticsearchExceptionTranslator.translateException(ElasticsearchExceptionTranslator.java:62)
at org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate.execute(ElasticsearchTemplate.java:540)
at org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate.doIndex(ElasticsearchTemplate.java:213)
at org.springframework.data.elasticsearch.core.AbstractElasticsearchTemplate.save(AbstractElasticsearchTemplate.java:204)
at org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository.lambda$save$5(SimpleElasticsearchRepository.java:172)
at org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository.executeAndRefresh(SimpleElasticsearchRepository.java:344)
at org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository.save(SimpleElasticsearchRepository.java:172)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:288)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:516)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:628)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:168)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:218)
at jdk.proxy2/jdk.proxy2.$Proxy131.save(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:218)
at jdk.proxy2/jdk.proxy2.$Proxy131.save(Unknown Source)
at com...ServiceImpl.sendToElastic(ServiceImpl.java:171)
at com...ServiceImpl.getIdAndSend(ServiceImpl.java:132)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
at org.springframework.util.concurrent.FutureUtils.lambda$toSupplier$0(FutureUtils.java:74)
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.RuntimeException: Connection refused
at org.springframework.data.elasticsearch.client.elc.ElasticsearchExceptionTranslator.translateException(ElasticsearchExceptionTranslator.java:61)
... 56 common frames omitted
Caused by: java.net.ConnectException: Connection refused
at org.elasticsearch.client.RestClient.extractAndWrapCause(RestClient.java:930)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:300)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:288)
at co.elastic.clients.transport.rest_client.RestClientTransport.performRequest(RestClientTransport.java:147)
at co.elastic.clients.elasticsearch.ElasticsearchClient.index(ElasticsearchClient.java:962)
at org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate.lambda$doIndex$6(ElasticsearchTemplate.java:213)
at org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate.execute(ElasticsearchTemplate.java:538)
... 55 common frames omitted
Caused by: java.net.ConnectException: Connection refused
at java.base/sun.nio.ch.Net.pollConnect(Native Method)
at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672)
at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:946)
at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.processEvent(DefaultConnectingIOReactor.java:174)
at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.processEvents(DefaultConnectingIOReactor.java:148)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor.execute(AbstractMultiworkerIOReactor.java:351)
at org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager.execute(PoolingNHttpClientConnectionManager.java:221)
at org.apache.http.impl.nio.client.CloseableHttpAsyncClientBase$1.run(CloseableHttpAsyncClientBase.java:64)
... 1 common frames omitted
I have double checked my url, port and credentials. How do i solve this problem?
In springboot 3 just creating ClientConfiguration bean is not enough, the configuration class needs to extend the class ElasticsearchConfiguration as well.
#Configuration
#Slf4j
#EnableElasticsearchRepositories(basePackages = "com....elastic")
public class ElasticConfig extends ElasticsearchConfiguration {
#Override
public ClientConfiguration clientConfiguration() {
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo("192.168.19.23:9200")
.usingSsl()
.withConnectTimeout(Duration.ofSeconds(5))
.withSocketTimeout(Duration.ofSeconds(3))
.withBasicAuth("elastic", "abc")
.build();
return clientConfiguration;
}
}
With this configuration ElasticsearchOperations, ElasticsearchClient and RestClient can be autowired as well.
Edit (P.J.Meisch): This is documented as well: https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.clients.restclient

MockRestServiceServer.verify() is failed when the test did not mock all of API in the project

My project have 2 APIs and I want to separate test for each API.
So I am trying to use MockRestServiceServer to mock my API but MockRestServiceServer requires all of API that I have in my project have to mock even it does not need.
My spring boot version:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
There are my code: using 2 schedules to call 2 APIs
#Scheduled(fixedDelay = 3000)
public void schedule1() {
restTemplate.getForEntity(URI.create("http://localhost:9090/api1"), String.class);
}
#Scheduled(fixedDelay = 3000)
public void schedule2() {
restTemplate.getForEntity(URI.create("http://localhost:9090/api2"), String.class);
}
And my test
#Test
void testSchedule1() {
mockServer = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();
mockServer
.expect(ExpectedCount.manyTimes(),
MockRestRequestMatchers.requestTo(new StringStartsWith("http://localhost:9090/api1")))
.andExpect(MockRestRequestMatchers.method(HttpMethod.GET))
.andRespond(MockRestResponseCreators.withStatus(HttpStatus.OK).body(""));
mockServer.verify(Duration.ofSeconds(10));
}
#Test
void testSchedule2() {
mockServer = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();
mockServer
.expect(ExpectedCount.manyTimes(),
MockRestRequestMatchers.requestTo(new StringStartsWith("http://localhost:9090/api2")))
.andExpect(MockRestRequestMatchers.method(HttpMethod.GET))
.andRespond(MockRestResponseCreators.withStatus(HttpStatus.OK).body(""));
mockServer.verify(Duration.ofSeconds(10));
}
As default, 2 schedules will run in the same thread. So schedule1 executed first, then the testSchedule1 passed and testSchedule2 always failed.
2022-04-02 21:50:30.374 ERROR 2284 --- \[ scheduling-1\] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:9090/api1": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:785) \~\[spring-web-5.3.18.jar:5.3.18\]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:751) \~\[spring-web-5.3.18.jar:5.3.18\]
at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:377) \~\[spring-web-5.3.18.jar:5.3.18\]
at com.example.demo1.test.Test.schedule1(Test.java:18) \~\[classes/:na\]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) \~\[na:na\]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) \~\[na:na\]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) \~\[na:na\]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) \~\[na:na\]
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) \~\[spring-context-5.3.18.jar:5.3.18\]
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) \~\[spring-context-5.3.18.jar:5.3.18\]
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) \~\[na:na\]
at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) \~\[na:na\]
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) \~\[na:na\]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) \~\[na:na\]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) \~\[na:na\]
at java.base/java.lang.Thread.run(Thread.java:833) \~\[na:na\]
Caused by: java.net.ConnectException: Connection refused: connect
at java.base/sun.nio.ch.Net.connect0(Native Method) \~\[na:na\]
at java.base/sun.nio.ch.Net.connect(Net.java:579) \~\[na:na\]
at java.base/sun.nio.ch.Net.connect(Net.java:568) \~\[na:na\]
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:588) \~\[na:na\]
at java.base/java.net.Socket.connect(Socket.java:633) \~\[na:na\]
at java.base/java.net.Socket.connect(Socket.java:583) \~\[na:na\]
at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:183) \~\[na:na\]
at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:498) \~\[na:na\]
at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:603) \~\[na:na\]
at java.base/sun.net.www.http.HttpClient.\<init\>(HttpClient.java:246) \~\[na:na\]
at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:351) \~\[na:na\]
at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:373) \~\[na:na\]
at java.base/sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1309) \~\[na:na\]
at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1242) \~\[na:na\]
at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1128) \~\[na:na\]
at java.base/sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:1057) \~\[na:na\]
at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76) \~\[spring-web-5.3.18.jar:5.3.18\]
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) \~\[spring-web-5.3.18.jar:5.3.18\]
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) \~\[spring-web-5.3.18.jar:5.3.18\]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:776) \~\[spring-web-5.3.18.jar:5.3.18\]
... 15 common frames omitted
2022-04-02 21:50:30.376 ERROR 2284 --- \[ scheduling-1\] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:9090/api2": Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:785) \~\[spring-web-5.3.18.jar:5.3.18\]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:751) \~\[spring-web-5.3.18.jar:5.3.18\]
at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:377) \~\[spring-web-5.3.18.jar:5.3.18\]
at com.example.demo1.test.Test.schedule2(Test.java:23) \~\[classes/:na\]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) \~\[na:na\]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) \~\[na:na\]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) \~\[na:na\]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) \~\[na:na\]
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) \~\[spring-context-5.3.18.jar:5.3.18\]
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) \~\[spring-context-5.3.18.jar:5.3.18\]
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) \~\[na:na\]
at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) \~\[na:na\]
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) \~\[na:na\]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) \~\[na:na\]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) \~\[na:na\]
at java.base/java.lang.Thread.run(Thread.java:833) \~\[na:na\]
Caused by: java.net.ConnectException: Connection refused: connect
at java.base/sun.nio.ch.Net.connect0(Native Method) \~\[na:na\]
at java.base/sun.nio.ch.Net.connect(Net.java:579) \~\[na:na\]
at java.base/sun.nio.ch.Net.connect(Net.java:568) \~\[na:na\]
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:588) \~\[na:na\]
at java.base/java.net.Socket.connect(Socket.java:633) \~\[na:na\]
at java.base/java.net.Socket.connect(Socket.java:583) \~\[na:na\]
at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:183) \~\[na:na\]
at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:498) \~\[na:na\]
at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:603) \~\[na:na\]
at java.base/sun.net.www.http.HttpClient.\<init\>(HttpClient.java:246) \~\[na:na\]
at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:351) \~\[na:na\]
at java.base/sun.net.www.http.HttpClient.New(HttpClient.java:373) \~\[na:na\]
at java.base/sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1309) \~\[na:na\]
at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1242) \~\[na:na\]
at java.base/sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1128) \~\[na:na\]
at java.base/sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:1057) \~\[na:na\]
at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76) \~\[spring-web-5.3.18.jar:5.3.18\]
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) \~\[spring-web-5.3.18.jar:5.3.18\]
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) \~\[spring-web-5.3.18.jar:5.3.18\]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:776) \~\[spring-web-5.3.18.jar:5.3.18\]
... 15 common frames omitted
2022-04-02 21:50:33.392 ERROR 2284 --- \[ scheduling-1\] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task
java.lang.AssertionError: No further requests expected: HTTP GET http://localhost:9090/api1
0 request(s) executed.
at org.springframework.test.web.client.AbstractRequestExpectationManager.createUnexpectedRequestError(AbstractRequestExpectationManager.java:213) ~[spring-test-5.3.18.jar:5.3.18]
at org.springframework.test.web.client.UnorderedRequestExpectationManager.matchRequest(UnorderedRequestExpectationManager.java:44) ~[spring-test-5.3.18.jar:5.3.18]
at org.springframework.test.web.client.AbstractRequestExpectationManager.validateRequest(AbstractRequestExpectationManager.java:97) ~[spring-test-5.3.18.jar:5.3.18]
at org.springframework.test.web.client.MockRestServiceServer$MockClientHttpRequestFactory$1.executeInternal(MockRestServiceServer.java:338) ~[spring-test-5.3.18.jar:5.3.18]
at org.springframework.mock.http.client.MockClientHttpRequest.execute(MockClientHttpRequest.java:110) ~[spring-test-5.3.18.jar:5.3.18]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:776) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:751) ~[spring-web-5.3.18.jar:5.3.18]
at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:377) ~[spring-web-5.3.18.jar:5.3.18]
at com.example.demo1.test.Test.schedule1(Test.java:18) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) ~[spring-context-5.3.18.jar:5.3.18]
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.3.18.jar:5.3.18]
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[na:na]
at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) ~[na:na]
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
After checked, I recognized If any schedule run first, the test case of that schedule will be passed.
I have checked the source code of MockRestServiceServer. It comes to AbstractRequestExpectationManager
in the verify method will call verifyInternal()
private int verifyInternal() {
if (this.expectations.isEmpty()) {
return 0;
}
if (!this.requestFailures.isEmpty()) {
throw new AssertionError("Some requests did not execute successfully.\n" +
this.requestFailures.entrySet().stream()
.map(entry -> "Failed request:\n" + entry.getKey() + "\n" + entry.getValue())
.collect(Collectors.joining("\n", "\n", "")));
}
int count = 0;
for (RequestExpectation expectation : this.expectations) {
if (!expectation.isSatisfied()) {
count++;
}
}
return count;
}
And the requestFailures is the map stores all failed requests (expected and unexpected)
#Override
public ClientHttpResponse validateRequest(ClientHttpRequest request) throws IOException {
RequestExpectation expectation;
synchronized (this.requests) {
if (this.requests.isEmpty()) {
afterExpectationsDeclared();
}
try {
// Try this first for backwards compatibility
ClientHttpResponse response = validateRequestInternal(request);
if (response != null) {
return response;
}
else {
expectation = matchRequest(request);
}
}
catch (Throwable ex) {
this.requestFailures.put(request, ex);
throw ex;
}
finally {
this.requests.add(request);
}
}
return expectation.createResponse(request);
}
If the schedule1 will be executed first, then it satisfied the condition: if (this.expectations.isEmpty()) first and the test case will be passed.
If the schedule1 executed after schedule1, the requestFailures will store the error of API 1, then it satisfied this condition: if (!this.requestFailures.isEmpty()) and the test case will be failed.
Is that MockRestServiceServer behavior? They want to mock all APIs?
If yes, please help me some alternative solution for my scenario.
Thanks

StoredProcedureItemReader not able to retry on java.sql.SQLTimeoutException

I am having difficulty in getting my StoredProcedureItemReader to Retry after it fails due to SQLTimeoutException.
Here is the configuration for my step process:
#Bean
public Step Step() throws Exception {
return stepBuilderFactory.get("Step")
.<Student, Student>chunk(100)
.reader(storedProcItemReader())
.processor(studentItemProcessor)
.writer(fileItemWriter())
.faultTolerant()
.retryLimit(5)
.retry(QueryTimeoutException.class)
.retry(SQLTimeoutException.class)
.backOffPolicy(backoffPolicy())
.build();
}
#Bean
#StepScope
public RetryableItemReader<Student> storedProcItemReader() throws Exception {
return studentItemReader.getDataFromDatabase(dataSource);
}
studentItemReader class file:
#Component
#StepScope
public class studentItemReader{
public RetryableItemReader<Student> getDataFromDatabase(DataSource dataSource) {
RetryTemplate retryTemplate = RetryTemplate.builder()
.maxAttempts(5)
.exponentialBackoff(1000, 2, 20000)
.retryOn(QueryTimeoutException.class)
.retryOn(SQLTimeoutException.class)
.build();
StoredProcedureItemReader<RegionResponse> reader = new StoredProcedureItemReader<>();
SqlParameter[] parameter = { new SqlParameter("#studentId",
java.sql.Types.INTEGER) };
PreparedStatementSetter statementValues = new PreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setInt(1, parameterValue);
}
};
reader.setDataSource(dataSource);
reader.setProcedureName("dbo.StudentReport");
reader.setParameters(parameter);
reader.setPreparedStatementSetter(statementValues);
reader.setRowMapper(new StudentRowMapper());
reader.setQueryTimeout(1500);
return new RetryableItemReader<>(reader, retryTemplate);
}
}
}
Retry:
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamReader;
import org.springframework.batch.item.database.StoredProcedureItemReader;
import org.springframework.retry.support.RetryTemplate;
public class RetryableItemReader<T> implements ItemStreamReader<T> {
private final StoredProcedureItemReader<T> delegate;
private final RetryTemplate retryTemplate;
public RetryableItemReader(StoredProcedureItemReader<T> delegate, RetryTemplate retryTemplate) {
this.delegate = delegate;
this.retryTemplate = retryTemplate;
}
#Override
public T read() throws Exception {
return retryTemplate.execute(context -> delegate.read());
}
#Override
public void open(ExecutionContext executionContext) throws ItemStreamException {
delegate.open(executionContext);
}
#Override
public void update(ExecutionContext executionContext) throws ItemStreamException {
delegate.update(executionContext);
}
#Override
public void close() throws ItemStreamException {
delegate.close();
}
}
I am seeing this in the logs where it isn't able to retry:
2021-09-09 19:21:10.405 [SimpleAsyncTaskExecutor-4] WARN c.z.hikari.pool.ProxyConnection:182 - HikariPool-1 - Connection ConnectionID:4 ClientConnectionId: bf81d056-0bc4-4657-b201-bc638d128f13 marked as broken because of SQLSTATE(HY008), ErrorCode(0)
java.sql.SQLTimeoutException: The query has timed out.
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:226)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.execute(SQLServerPreparedStatement.java:505)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
at com.zaxxer.hikari.pool.HikariProxyCallableStatement.execute(HikariProxyCallableStatement.java)
at org.springframework.batch.item.database.StoredProcedureItemReader.openCursor(StoredProcedureItemReader.java:213)
at org.springframework.batch.item.database.AbstractCursorItemReader.doOpen(AbstractCursorItemReader.java:428)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:150)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader.open(RetryableItemReader.java:25)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader$$FastClassBySpringCGLIB$$7ad4b84a.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader$$EnhancerBySpringCGLIB$$a742dbe0.open(<generated>)
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103)
at org.springframework.batch.core.step.item.ChunkMonitor.open(ChunkMonitor.java:114)
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103)
at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:311)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:205)
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:138)
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:135)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.lang.Thread.run(Thread.java:834)
2021-09-09 19:21:10.406 [SimpleAsyncTaskExecutor-3] DEBUG o.s.retry.support.RetryTemplate:324 - Retry: count=0
2021-09-09 19:21:10.406 [SimpleAsyncTaskExecutor-3] DEBUG o.s.retry.support.RetryTemplate:324 - Retry: count=0
2021-09-09 19:21:10.408 [SimpleAsyncTaskExecutor-3] DEBUG o.s.retry.support.RetryTemplate:324 - Retry: count=0
2021-09-09 19:21:10.522 [SimpleAsyncTaskExecutor-1] ERROR o.s.batch.core.step.AbstractStep:237 - Encountered an error executing step slaveStep in job Pit-Extract
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:153)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader.open(RetryableItemReader.java:25)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader$$FastClassBySpringCGLIB$$7ad4b84a.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader$$EnhancerBySpringCGLIB$$a742dbe0.open(<generated>)
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103)
at org.springframework.batch.core.step.item.ChunkMonitor.open(ChunkMonitor.java:114)
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103)
at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:311)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:205)
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:138)
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:135)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.springframework.dao.QueryTimeoutException: Executing stored procedure; SQL [{call dbo.StudentReport(?)}]; The query has timed out.; nested exception is java.sql.SQLTimeoutException: The query has timed out.
at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:76)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.springframework.batch.item.database.StoredProcedureItemReader.openCursor(StoredProcedureItemReader.java:229)
at org.springframework.batch.item.database.AbstractCursorItemReader.doOpen(AbstractCursorItemReader.java:428)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:150)
... 21 common frames omitted
Caused by: java.sql.SQLTimeoutException: The query has timed out.
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:226)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.execute(SQLServerPreparedStatement.java:505)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
at com.zaxxer.hikari.pool.HikariProxyCallableStatement.execute(HikariProxyCallableStatement.java)
at org.springframework.batch.item.database.StoredProcedureItemReader.openCursor(StoredProcedureItemReader.java:213)
... 23 common frames omitted
2021-09-09 19:21:10.522 [SimpleAsyncTaskExecutor-4] ERROR o.s.batch.core.step.AbstractStep:237 - Encountered an error executing step slaveStep in job Pit-Extract
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:153)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader.open(RetryableItemReader.java:25)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader$$FastClassBySpringCGLIB$$7ad4b84a.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader$$EnhancerBySpringCGLIB$$a742dbe0.open(<generated>)
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103)
at org.springframework.batch.core.step.item.ChunkMonitor.open(ChunkMonitor.java:114)
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103)
at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:311)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:205)
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:138)
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:135)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.springframework.dao.QueryTimeoutException: Executing stored procedure; SQL [{call dbo.StudentReport(?)}]; The query has timed out.; nested exception is java.sql.SQLTimeoutException: The query has timed out.
at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:76)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.springframework.batch.item.database.StoredProcedureItemReader.openCursor(StoredProcedureItemReader.java:229)
at org.springframework.batch.item.database.AbstractCursorItemReader.doOpen(AbstractCursorItemReader.java:428)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:150)
... 21 common frames omitted
Caused by: java.sql.SQLTimeoutException: The query has timed out.
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:226)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.execute(SQLServerPreparedStatement.java:505)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
at com.zaxxer.hikari.pool.HikariProxyCallableStatement.execute(HikariProxyCallableStatement.java)
at org.springframework.batch.item.database.StoredProcedureItemReader.openCursor(StoredProcedureItemReader.java:213)
... 23 common frames omitted
2021-09-09 19:21:10.582 [SimpleAsyncTaskExecutor-2] WARN c.z.hikari.pool.ProxyConnection:182 - HikariPool-1 - Connection ConnectionID:5 ClientConnectionId: 161fd25b-5a39-465c-b1a6-8116952b1972 marked as broken because of SQLSTATE(HY008), ErrorCode(0)
java.sql.SQLTimeoutException: The query has timed out.
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:226)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.execute(SQLServerPreparedStatement.java:505)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
at com.zaxxer.hikari.pool.HikariProxyCallableStatement.execute(HikariProxyCallableStatement.java)
at org.springframework.batch.item.database.StoredProcedureItemReader.openCursor(StoredProcedureItemReader.java:213)
at org.springframework.batch.item.database.AbstractCursorItemReader.doOpen(AbstractCursorItemReader.java:428)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:150)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader.open(RetryableItemReader.java:25)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader$$FastClassBySpringCGLIB$$7ad4b84a.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader$$EnhancerBySpringCGLIB$$a742dbe0.open(<generated>)
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103)
at org.springframework.batch.core.step.item.ChunkMonitor.open(ChunkMonitor.java:114)
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103)
at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:311)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:205)
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:138)
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:135)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.lang.Thread.run(Thread.java:834)
2021-09-09 19:21:10.583 [SimpleAsyncTaskExecutor-2] ERROR o.s.batch.core.step.AbstractStep:237 - Encountered an error executing step slaveStep in job Pit-Extract
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:153)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader.open(RetryableItemReader.java:25)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader$$FastClassBySpringCGLIB$$7ad4b84a.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader$$EnhancerBySpringCGLIB$$a742dbe0.open(<generated>)
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103)
at org.springframework.batch.core.step.item.ChunkMonitor.open(ChunkMonitor.java:114)
at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103)
at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:311)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:205)
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:138)
at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:135)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.springframework.dao.QueryTimeoutException: Executing stored procedure; SQL [{call dbo.StudentReport(?)}]; The query has timed out.; nested exception is java.sql.SQLTimeoutException: The query has timed out.
at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:76)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.springframework.batch.item.database.StoredProcedureItemReader.openCursor(StoredProcedureItemReader.java:229)
at org.springframework.batch.item.database.AbstractCursorItemReader.doOpen(AbstractCursorItemReader.java:428)
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:150)
... 21 common frames omitted
Caused by: java.sql.SQLTimeoutException: The query has timed out.
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:226)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.execute(SQLServerPreparedStatement.java:505)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
at com.zaxxer.hikari.pool.HikariProxyCallableStatement.execute(HikariProxyCallableStatement.java)
at org.springframework.batch.item.database.StoredProcedureItemReader.openCursor(StoredProcedureItemReader.java:213)
... 23 common frames omitted
2021-09-09 19:21:12.888 [custom-executor1] ERROR o.s.batch.core.step.AbstractStep:237 - Encountered an error executing step masterStep in job Student-Info-Extract
org.springframework.batch.core.JobExecutionException: Partition handler returned an unsuccessful step
at org.springframework.batch.core.partition.support.PartitionStep.doExecute(PartitionStep.java:112)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:68)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:68)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:169)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:137)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:319)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:147)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Please let me what mistake I am doing here. Thanks in advance!
Your RetryableItemReader only retries the read operation, but the timeout is happening while initializing the reader, ie in the open method. This can be seen here:
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:153)
at gov.va.med.ccrs.pit.extract.retry.RetryableItemReader.open(RetryableItemReader.java:25)
...
This method is not retried in your RetryableItemReader. You can make it retryable as you did for the read method, something like:
#Override
public void open(ExecutionContext executionContext) throws ItemStreamException {
retryTemplate.execute(new RetryCallback<Object, ItemStreamException>() {
#Override
public Object doWithRetry(RetryContext retryContext) throws ItemStreamException {
delegate.open(executionContext);
return null;
};
});
}
That said, I would investigate why the timeout is happening as it could happen again down the road when reading actual data (even if this is retried).

Unable to bind with active directory

I'm new in this domain and trying to bind with active directory using spring ldap client in java. I have already googled this and tried every given solution on internet but it didn't work for me. I'm getting following exception:
021-08-02T14:14:04,377 DEBUG [AbstractContextSource] - Got Ldap context on server [********]
2021-08-02T14:14:04,381 ERROR [UserService] - #### NamingException #### {}
org.springframework.ldap.UncategorizedLdapException: Uncategorized exception occured during LDAP processing; nested exception is javax.naming.NamingException: [LDAP: error code 1 - 000004DC: LdapErr: DSID-0C090A71, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v3839�]; remaining name ‘/’
at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:228) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:397) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:309) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:642) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:578) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.ldap.core.LdapTemplate.find(LdapTemplate.java:1840) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.ldap.core.LdapTemplate.find(LdapTemplate.java:1861) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.ldap.core.LdapTemplate.findOne(LdapTemplate.java:1869) ~[spring-ldap-core-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.data.ldap.repository.query.AbstractLdapRepositoryQuery.execute(AbstractLdapRepositoryQuery.java:70) ~[spring-data-ldap-2.3.9.RELEASE.jar:2.3.9.RELEASE]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryQueryMethodInvoker$$Lambda$1419/947388427.invoke(Unknown Source) ~[?:?]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:159) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:138) ~[spring-data-commons-2.5.1.jar:2.5.1]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.7.jar:5.3.7]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.7.jar:5.3.7]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.7.jar:5.3.7]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.7.jar:5.3.7]
at com.sun.proxy.$Proxy79.findUserByUsername(Unknown Source) ~[?:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_45]
at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_45]
Dependencies:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-ldap</artifactId>
<version>${data.ldap.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
<version>${ldap.core.version}</version>
</dependency>
Following is what I've tried:
#Bean
public LdapContextSource contextSource()
{
LOGGER.atDebug().log("using given ldap server config: {}", ldapServerConfig);
LdapContextSource contextSource = new LdapContextSource();
contextSource.setUrl(ldapServerConfig.getUrl());
contextSource.setBase(ldapServerConfig.getBaseDn());
contextSource.setUserDn(ldapServerConfig.getUsername());
contextSource.setPassword(ldapServerConfig.getPassword());
contextSource.setAnonymousReadOnly(ldapServerConfig.isReadOnlyConnection());
//TODO: To add the support of TLS v1.0/v1.2/v1.3
if (ldapServerConfig.isTlsEnabled())
{
ExternalTlsDirContextAuthenticationStrategy dirContextAuthenticationStrategy = new ExternalTlsDirContextAuthenticationStrategy();
contextSource.setAuthenticationStrategy(dirContextAuthenticationStrategy);
}
return contextSource;
}
#Bean
public LdapTemplate ldapTemplate(ContextSource pooledContextSource, ContextSource contextSource)
{
LOGGER.atInfo().log("connection pooling enabled: {}", ldapServerConfig.isConnectionPooling());
return ldapServerConfig.isConnectionPooling() ? new LdapTemplate(pooledContextSource) : new LdapTemplate(contextSource);
}
private ResponseEntity<ILdapResponse> authenticate(String username)
{
ResponseEntity<ILdapResponse> responseEntity;
ILdapResponse ldapResponse;
try
{
User user = userRepository.findUserByUsername(username);
Furthermore I've tried to connect with the test server and it's working fine and successfully connected. Following are the test server details
ldap.server.url=ldap://ldap.forumsys.com:389/
ldap.server.baseDn=dc=example,dc=com
ldap.server.username=cn=read-only-admin,dc=example,dc=com
ldap.server.password=password
Also I've tried to connect with the ldap console and got the successful PROD environment connection.I don't know what i'm missing in client due to which i'm unable to connect. Please guide me if i'm missing anything. Thanks in advance
ldapsearch -d 3 -x -h <url> -p 389 -D <DN/username> -W -b <base dn> cn

Using Apache Camel for routing gRPC traffic (using the same port per route)

I'm trying to implement a gateway using springboot & apache camel to manage routing gRPC traffic of multiple microservices.
The goal is to expose all the traffic using the same hostname & port to a single entry-point for our client.
I've started with two routes as described below
AuthenticationRoute
#Component
public class AuthenticationRoute extends RouteBuilder{
#Override
public void configure() throws Exception {
AuthenticationResponse fallbackResponse =
AuthenticationResponse.newBuilder().setMessage("FAILED").setStatus("ORS-400").build();
from("grpc://localhost:9090/com.erable.services.impl.AuthenticationService=authenticate")
.circuitBreaker()
.to("grpc://localhost:4041/com.erable.services.impl.AuthenticationService?method=authenticate")
.log(LoggingLevel.WARN, "FALLBACK ALERT")
.onFallback()
.process(exchange -> exchange.getIn().setBody(fallbackResponse, AuthenticationResponse.class))
.end();
}
}
EquipmentListQueryRoute
#Component
public class EquipmentListQueryRoute extends RouteBuilder{
#Override
public void configure() throws Exception {
EquipmentListResponse fallbackResponse =
EquipmentListResponse.newBuilder().setMessage("FAILED").setStatus("ORS-400").build();
from("grpc://localhost:9090/com.erable.services.impl.EquipmentService=equipmentListQuery")
.circuitBreaker()
.to("grpc://localhost:4042/com.erable.services.impl.EquipmentService?method=equipmentListQuery")
.log(LoggingLevel.WARN, "FALLBACK ALERT")
.onFallback()
.process(exchange -> exchange.getIn().setBody(fallbackResponse, EquipmentListResponse.class))
.end();
}
}
When running the project, I gor the following exception :
Caused by: java.io.IOException: Failed to bind
at io.grpc.netty.NettyServer.start(NettyServer.java:264) ~[grpc-netty-1.30.2.jar:1.30.2]
at io.grpc.internal.ServerImpl.start(ServerImpl.java:183) ~[grpc-core-1.30.2.jar:1.30.2]
at io.grpc.internal.ServerImpl.start(ServerImpl.java:90) ~[grpc-core-1.30.2.jar:1.30.2]
at org.apache.camel.component.grpc.GrpcConsumer.doStart(GrpcConsumer.java:78) ~[camel-grpc-3.6.0.jar:3.6.0]
at org.apache.camel.support.service.BaseService.start(BaseService.java:115) ~[camel-api-3.6.0.jar:3.6.0]
... 32 more
Caused by: java.net.BindException: Address already in use: bind
at sun.nio.ch.Net.bind0(Native Method) ~[?:?]
at sun.nio.ch.Net.bind(Net.java:461) ~[?:?]
at sun.nio.ch.Net.bind(Net.java:453) ~[?:?]
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:227) ~[?:?]
at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:134) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:550) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.bind(DefaultChannelPipeline.java:1334) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:506) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:491) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:973) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:248) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:356) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164) ~[netty-common-4.1.52.Final.jar:4.1.52.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472) ~[netty-common-4.1.52.Final.jar:4.1.52.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500) ~[netty-transport-4.1.52.Final.jar:4.1.52.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.52.Final.jar:4.1.52.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.52.Final.jar:4.1.52.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.52.Final.jar:4.1.52.Final]
at java.lang.Thread.run(Thread.java:834) ~[?:?]
Does this mean that I can't use the same host:port to expose multiple camel-gRPC routes?
This scenario works fine when using jetty or netty-http or undertow:http to route rest apis.
This option is not implemented currently
Created a JIRA issue to track this functionality
https://issues.apache.org/jira/browse/CAMEL-15883

Resources