What is the retry logic to int-http:outbound-gateway? - spring-integration

I have a int-http:outbound-gateway in my spring integration config file that consumes a rest service.
I am trying to start the error handling part of the implementation, but I would like first to understand how the retry works. I can notice that when an error occurs, let's say a bad request, spring integration framework seems to retry to send the request to the rest service and, in fact, depending on the error - http code - I would like to handle it in a different way.
How can I avoid the retry depending on the http response code?

There is no inherent retry; retry is implemented using a retry advice.
It can be customized for different exception types, but not for status codes; you would need a custom advice for that - the documentation explains how to write one.

Related

Exception handling in xml based spring integration

How to publish exception in error-channel whenever we encounter any exception in any of the route. We dont want to catch exception manually. It should automatically routed to error-channel?
No, it can't go automatically to the error-channel. That's not how plain Java works. So, if you call some java code you expect an exception from there and you definitely use a try...catch construction.
The error-channel makes sense only in the processes not started by end-users, some active processes like task executors and schedulers. For this purpose we indeed provide an error-channel hook do not let downstream error to disappear.
Another way to do a-la try...catch, but still send to the error-channel can be done via Messaging Gateway: https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints-chapter.html#gateway-error-handling. This way the Framework wraps the whole flow to the try...catch and sends an ErrorMessage to the configured errorChannel.
Also for per-service purpose we provide an ExpressionEvaluatingRequestHandlerAdvice with its own in-scope failureChannel: https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints-chapter.html#expression-advice

How to call security setup when message received using Spring Integration

I currently am using Spring Integration to get messages off of a queue and send them to a service using a service activator. My issue is that the service I am calling requires a security context to be in place for the current thread. This can be setup by calling a no-argument method, handleAuthentication(), of another bean. I am wondering what the best way is to call this whenever a new message is received, prior to calling the service activator service? I was originally thinking I would chain together two service activators, with the first one calling handleAuthentication(), but this seems incorrect as handleAuthentication() does not require any information from the actual message.
Yes, your assumption about the security handling is correct. It is really just a side-effect aspect which should not be tied with the business logic.
Therefore we should use something which allows us to follow with the same behavior in the program. It is called as an Aspect in the programming as well.
For this purpose Spring Integration suggests a hook like MessageChannelInterceptor, where you can implement your handleAuthentication() exactly in the preReceive() callback, according to your explanation.
Another trick can be achieved with the <request-handler-advice-chain> and MethodInterceptor implementation which should populate the SecurityContext into the current thread just before target service invocation.

spring amqp ReplyRequiredException

I have a request/reply implemented using spring integration and amqp. The requests may take long time to process (they may take even an hour for some cases) , for some reason the client throws exception -
Exception in thread "main" org.springframework.integration.handler.ReplyRequiredException: No reply produced by handler 'client', and its 'requiresReply' property is set to true.
My client config is below.
<int-amqp:outbound-gateway
id="client"
request-channel="in"
reply-channel="res"
exchange-name="reportingServer"
routing-key-expression="'report.req.'+headers.id"
amqp-template="amqpTemplate" requires-reply="true">
</int-amqp:outbound-gateway>
I believe reply-timeout default value is -1, means wait indefinitely, but not sure why its not working, any help would be appreciated.
Also are there any known issues with implementing such long waiting operations in amqp or it should be just fine?
Thank You
It will be fine as long as you don't have too many concurrent requests - it won't scale very well if you have gazillions of threads hanging waiting for a reply.
If you need to scale it, you could devise an asynchronous equivalent with a pair of outbound and inbound adapters, but it's a little more involved than using a gateway and the actual implementation will depend on the rest of your flow. Essentially you'll have to set up the replyTo header to cause the reply to come to the inbound adapter.
If you have a simple <gateway/> upstream of the AMQP gateway, you'll need to be sure that the replyChannel header is not lost. See Header Channel Registry in this section.

Serial processing in spring integration

Is it possible to have serial processing in spring integration that is the response of one request is get to the next as its request. I have a requirement where only after getting response from service-1 I can initiate call to service-2. This was suggested so because only service-1 has a roll back service implemented.
Is it possible to control which request is processed first, I want request 1 to be processed first. Is this also possible
It really depends on what you are trying to do, but the general solution would be to use a <publish-subscribe-channel/> set the order on the first service to "1" and the second to "2".
By default, the second service will only be called if the first is successful.
If you need to aggregate the results, add an aggregator downstream of both services.

How do I simulate transient errors with Azure Database?

I am working with the Transient Fault Handling Application Block (TFHAB) to define a retry policy when interfacing with an Azure Database. I'm wondering if there is a way to invoke a throttling response in order to plan and handle likely production scenarios?
I could place an SQL command in a loop and run it until I invoke a response however presumably this is not considered to be "best practice"?
Can anyone suggest some practical ways in which I can test my transient error handling logic?
Look at combining Testing Transient errors in Azure and the list of error codes returned by Windows Azure SQL Database, and see if you can mock in the behavior that you are testing. Beyond unit testing I don't think that you are going to be able to 'simulate' errors because these errors are coming from SQL via the TDS protocol, which will be difficult to intercept. Your need would be a good candidate for a fork of the application block where you could inject a simulator.
I've managed to develop some code that allows you to reliably generate transient errors in Azure SQL Databases. You can find the code at: https://github.com/robdmoore/SQLAzureTransientDemo
My recommendation to you is dependency injection:) To eloborate, your higher level client code should not take a direct dependency to azure, put the client SDK behind an interface and pass that interface as dependency to your higher level client code. Pass the actual sdk for production code as the interface implementation and for your tests pass a test implementation of the interface where you can return any error code or response you want.

Resources