Spring Retry Circuit breaker opening for all exceptions - spring-retry

I was trying to use Spring Retry Circuit Breaker. My requirement is to open the Circuit only for repetitive exceptions of a specific type. And for all other exceptions, I would like to pass the exception back to the caller without opening the circuit. What I am observing is that the Circuit is opening for all types of Exceptions, not just the specific exception. Wondering if this is how it is designed to work?
My requirement: When I call a remote service, I would like to open the service only for any network errors. If I receive any data validation error from remote service, I would just like to pass a meaningful exception back to the business layer.
As I was playing with the framework, I see that the circuit is opening for all exceptions. Can someone advise if the above requirement can be achieved with Spring Retry Circuit breaker? If yes, could you point to some sample code?
Thanks in advance,
B Jagan

Yes; that's the way it works; when you include or exclude exception types, it relates to the max attempts.
When a "retryable" exception is thrown, the circuit won't go open until maxAttempts have occurred within openTimeout; if an exception is not retryable, the circuit goes open on the first attempt.
You would need a custom retry policy to do what you want.

Related

Connectivity issues when calling a controller endpoint, how can we deal with it? [Spring and Kotlin]

I have some service method used in my controller endpoint whose logic is not fully executed when connectivity issues arise (as you would expect). I am looking for a potential approach, rather than using a try and catch block within the service method. What is the recommended way to go? Is there any "rollback" functionality that can be injected in Spring whereby if something happens during the executing of the service logic then it rolls back?
Thank you

Spring Integration JMS - Spring code does commit on RuntimeException

I would like to ask experienced Spring Integration developers or even code authors regarding weird behavior Im experiencing with my code. The issue is that Spring Code executes COMMIT on my RuntimeException. So here is my setup:
1.
I have standard JMS inbound channel adapter configured using
<jms:message-driven-channel-adapter />
I have transactionManager which implements the Best effort 1PC pattern - that one available in Spring, ChainedTransactionManager.
Im consuming messages in simple testing flow where the JMS inbound adapter only publishes to direct channel and via one transformer endpoint the converted message is published to another direct endpoint where the handler which is ServiceActivator intentionally throws my application exception which extends RuntimeException.
Now when I debug the whole flow and when Im stepping through the Spring internal code I always end in place where the configured transaction manager calls COMMIT and thus my ChainedTransactionManager executes COMMIT as well despite Im simulating error and thus clear rollback scenario. The breakpoint in the rollback method is not hit at all.
What can I have wrong?
Now I have gone through the code again and even the Spring code sets the status to RollbackOnly and executes some exception handlers but at the end it still goes on successfully and ultimately it calls the commit line as shown on the screenshot and chainedTransactionManager instructs its local TMs to commit as well.
Im hoping there is some detail/mistake Im not able to spot :) Thanks!
Screenshot from class .m2\repository\org\springframework\spring-jms\5.2.3.RELEASE\spring-jms-5.2.3.RELEASE-sources.jar!\org\springframework\jms\listener\AbstractPollingMessageListenerContainer.java

JMS message processing with spring integration in cloud environment

I'm currently trying to refactor the processing of JMS messages to work in a distributed/cloud environment. To allow a better retry and error handling the messages are first stored to the database with a JPA entity and then read by spring integration jpa inbound adapter. This works fine as long as just a single instance of my service is running. However when multiple instances are running, the instances try to process the same message even after introducing a processing state on the persisted messages.
I have already tried to save the JMS messages in a JDBC message store, however then I would have to define a group identifier according to which an instance could select a message which is not really possible since the number of instances is dynamic and I can not assign a group id for each instance. Another possibility could be some kind of distributed lock with a LockRegistry but I couldn't make that work.
Do you have any hint/advice how I could implement the following requirements the best with spring integration:
JMS message should be persisted
Any instance can pick up the message and process it
If the processing fails there will be a retry for x times (could also be retried by another instance)
If an instance crashes or gets killed during the processing the message must not be lost
Is there maybe some spring-cloud component which could be helpful?
I'm happy about every hint in which direction I should go.

springBoot ConcurrentKafkaListenerContainerFactory what if downstream is down?

I'm a bit puzzled with ConcurrentKafkaListenerContainerFactory and setErrorHandler(org.springframework.kafka.listener.ErrorHandler)
Could you give me some advice please?
I have to pass Kafka message to external system. Right now ErrorHandler is rather naive. It sends message to dead-letter-queue if message handler throws exception. Message handler could throw exception due to two reasons:
business checks violation
external system is unavailable
It's ok to send message to dead-letter-queue if business checks raise exception.
It's wrong to send message to dead-letter queue if external system is unavailable. I have to implement some sort of backoff and retry to consume and handle event until external system comes back alive.
I would like to see if there is some Spring receipt for such case.
Thanks!
With the recent new release (2.3) you can specify a back off for retrying deliveries; you can also configure which exceptions are retryable.
The SeekToCurrentErrorHandler can be configured to treat certain exceptions as fatal, disabling retry; you can also now add a BackOff between redelivery attempts for failed deliveries.
Note that 2.3 requires Spring Boot 2.2; which is currently available as a release candidate and will be released soon.

camel, JMS, CLIENT_ACKNOWLEDGE mode

I know that Camel's JMS component, for receiving messages, uses Springs DefaultMessageListenerContainer. It can be configured to use CLIENT_ACKNOWLEDGE mode for acknowledging messages. My question is, when exactly the message.acknowledge() method gets called? Is it called internally by the spring's listener container?
Or can I somehow acknowledge message at my will?
I'd like to avoid scenario that messages get lost because my app crashed during processing of these messages and making it transactional seems a bit too heavy for me
OK. After some some debugging and scanning throug source code I've found out that Camel uses spring MessageListenerContainers. The AbstractMessageListenerContainer, in case of CLIENT_AKNOWLEDGE mode, invokes comitIfNecessary method acknowledging message. This happens only AFTER registered MessageListener processes message succesfully (no exceptions)
Camel uses EndpointMessageListener which, eventually, invokes process method of next processor (or Producer) down the route. As this is classic chain of responsibilities, if any processor down the route throws exception or sets exception on the Exchange, it will be re-thrown by EndpointMessageListener preventing the AbstractMessageListener to acknowledge message.

Resources