non-Controller SpringBoot exception interceptor - spring-boot

I have a spring boot microservice with no controller endpoints. It operates entirely on a workflow using inbound-channel-adapter to query databases and perform some Service action when necessary.
I'd like to intercept all exceptions and judiciously send an alert to the appropriate parties when appropriate.
`#ControllerAdvice doesn't cut it, because there are no controllers.
Any recommendations on how to trap exceptions via an ExceptionHandler or Filter or other means?
Our app uses a org.springframework.integration.handler.LoggingHandler to log exceptions, extending that could be an option. I'd prefer not to have all my services extend a single base class that defines an #ExceptionHandler.
What is the "spring way" to trap exceptions from workflow channels and send notifications (email/slack/otherwise) to the appropriate user?

As Martin points in his comment, an errorChannel approach is used Spring Integration to handle exceptions in the flow. See error-channel option on that inbound-channel-adapter. It is errorChannel by default and it has indeed a LoggingHandler as a subscriber. You can stay with that global errorChannel as is and just have your own service-activator as a subscriber. Or you can configure your own, flow-specific error channel and its subscriber.
See more in documentation:
https://docs.spring.io/spring-integration/docs/current/reference/html/error-handling.html#error-handling

Related

When an Exception is thrown in a provider-side ActiveMq BrokerFilter send method, how can the JMS sender subscribe as listener to that exception?

We implemented a filter, or plugin, in ActiveMq broker that intercepts inbound messages and validates them from a security standpoint.
We are needing a programmer friendly way of receiving these exceptions on the producer side (ideally not at connection level, but at session or producer level, since they may need session specific reaction).
We are doing message level authorization in the broker side in the following way: In the ActiveMq provider (server) we implement BrokerFilter (plugin) in order to intercept the incoming JMS message, and validate a JWT access token attached to the message as property. If the JWT token is valid, then the message is let through downstream chain, if it is not valid, a SecurityException is thrown.
We notice that the message does reach back to the sending JVM which reports that no ExceptionListener instances registered for the specific exception.
Our question is, where can we best register an ExceptionListener in Spring JMS for this scenario? We have direct access to the producer and JMS session, but not to the JMS connection.
It is true that registering an ExceptionListener to the connection would be useful for connection level events, but for session level events it may make the code more understandable and cohesive if we could register such exception listeners locally to the session or producer, since they are kind of direct responses to a message send attempt.
Of course it would be also possible to implement local exception listeners via connection level and a thread local structure of local listeners, but i am wondering if JMS or Spring already provides such possibility of the session or producer finding out directly that their message was not authorized, so that they answer upstream to calling microservice rather then retyrying to send it for instance.
We are using persistent messages but unsure if we do synchronous or asynchronous send. I believe on asynchronous send, an ExceptionListener of some kind will be called back on such an event (exception thrown in BrokerFilter.send method). While on the synchronous send perhaps the exception will directly be thrown there (but the thread blocking may decrease robustness of the microservice).
This is solvable with connection.setExceptionListener but to us it would likely be more convenient a session.setExceptionListener or even a message request level listener.
We would like to see any other options possible with Spring JMS except registering an exception listener at connection level and except synchronous send, if any such other options are possible.
Since Spring JMS uses the JMS API then you're pretty much limited to what the JMS API provides and it doesn't provide a session or request level exception listener. It provides a connection level exception listener for exceptions which are reported asynchronously and normal Java checked exceptions for the synchronous use-case.

Trying to redesign JMS configuration as Spring Integration: Redelivery policies

My legacy configuration exposes a ConnectionFactory #Bean of type ActiveMQConnectionFactory, with custom redelivery through activeMQConnectionFactory.setRedeliveryPolicy(..).
I found out that Spring Integration DSL allows redeliveries on the handle operation as well by means of RequestHandlerRetryAdvice, which can be configured for instance with an ExponentialBackOffPolicy.
I am wondering if they are triggering the same code at the lower level (not sure its a client thing or a signaling thing to the broker), and if not, whether they are equivalent and whether can I safely replace the abstract version without missing any configuratbility
No; it's completely different and has nothing to do with JMS and retrying incoming deliveries.
The retry advice is generally used to retry outgoing requests, e.g. an http request, or a send to JMS.

Asynchronous push of messages in channel (spring-integration)

I have a simple JMS topic listener that i would like to hook with a spring-integration chain.
Basically, when a JMS message is received in the listener it has to be pushed into the chain's channel. Eventually the message is processed and pushed to an outbound-channel-adapter to be consumed.
The Spring Integration documentation mentions the use of asynchronous gateways but that uses Futures.
Isn't there a simple way to just put the message on a channel?
If there is an example that you can point to it would be great.
Thanks
Regards
Martin
If you want to run the flow on the listener thread, simply use a regular gateway (not an async one); this will allow the message to roll-back if the flow fails for any reason.
If you want to "fire and forget" you can make the request channel from the gateway an ExecutorChannel - see here.

service activator acting as outbound gateway for invoking bean method

I am new to spring integration and was going through the definition of service activator. The definition says that it is used to call a method and wrap the result in the response message. The definition also tells that it is a outbound gateway for invoking the bean method. I am not clear on the second statement. As I understand outbound gateway is to send the request from the application to external application and get the response back into the application. So, if a bean is invoked, it is invoked within the application and hence it should be inbound gateway right. Please let me know where I am wrong.
There are two types of integration - with external systems using various protocols, and with legacy java code using method invocation.
Within that, there are one-way integrations (provided by channel adapters) and two-way integration (request/response, provided by gateways). In each case, the integration can be inbound to the message flow, or outbound from it.
The <int: .../> namespace provides inbound and outbound channel adapters for invoking legacy code from the messaging flow, in the latter case (outbound) the method return type must be null. You could also invoke the same method with a service activator, but the channel adapter is preferred because it's clear it's a one-way integration.
On the inbound side, the messaging gateway (<int:gateway/>) is provided to allow legacy java code interact with the messaging flow ("call" it) without any specific dependencies.
There is no <int:outbound-gateway/> for invoking a method because the service activator provides that functionality.
If you can point us to the documentation that caused the confusion, we can try to improve it; please open a documentation JIRA issue.

how do we configure multiple pollers to send messages to one transformer

How do i get multiple pollers of same type to route messages to a single transformer .I don't mind having the messages queued before the transformer
Well, I think you just want to reuse a message flow for all your <int-mail:imap-idle-channel-adapter>s. It's just enough to configure them all to the same channel.
Actually there is no difference with classical OOP design, when you inject the same service to different actions, like MVC controller, or JMS listeners.
But here we do exactly the same, but inject a MessageChannel to send results of those entry point to it and don't think what's going on underneath.
Please, read more books about Enterprise Integration Patterns

Resources