service activator acting as outbound gateway for invoking bean method - spring

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.

Related

OpenTelemetry: Context propagation using messaging (Artemis)

I wrote some micro-services using Quarkus that communicate via Artemis. Now I want to add OpenTelemetry for tracing purpose.
What I already tried is to call service B from service A using HTTP/REST. Here the trace id from service A is automatically added to the header of the HTTP request and used in service B. So this works fine. In Jaeger I can see the correlation.
But how can this be achieved using Artemis as messaging system? Do I have to (manually) add the trace id from service A into the message and read it in service B to setup somehow the context (don't know whether this is possible)? Or is there possibly an automatism like for HTTP requests?
I would appreciate any assistance.
I have to mention at this point that I have little experience with tracing so far.
There is no quarkus, quarkiverse extension or smallrye lib that provides integration with Artemis and OpenTelemetry, yet.
Also, OpenTelemetry massaging spec is being worked at the moment, because the correct way to correlate sent, received messages and services is under definition at the OTel spec level.
However, I had exactly the same problem as you and did a manual instrumentation that you can use as inspiration: quarkus-observability-demo-activemq
It will correlate the sent service as parent of receiving end.

What’s the difference between AbstractMessageSource and MessageProducerSupport in Spring Integration?

When developing inbound channel adapters, I couldn’t find any place that mentions the differences between AbstractMessageSource and MessageProducerSupport in Spring Integration. I’m asking this question in the context of reactive streams, so I’m actually looking at AbstractReactiveMessageSource, but I guess it doesn’t matter for my question. I also wonder whether MessageProducerSupport supports project reactor and doesn’t have an equivalent to AbstractReactiveMessageSource.
There is some documentation about these types of components: https://docs.spring.io/spring-integration/docs/current/reference/html/overview.html#finding-class-names-for-java-and-dsl-configuration
The inbound message flow side has its own components, which are divided into polling and listening behaviors.
So, the MessageProducerSupport is for those protocols which provide a listening callback for us. So, we can hook up into that, build message and produce it into a channel provided by the MessageProducer. So, it is self-eventing component which really has everything to listen to the source system and produce messages from the callback. This type of channel adapters called event-driven and samples of them are JMS, AMQP, HTTP, IMAP, Kinesis etc.
From here it is wrong to try to compare the MessageProducerSupport with an AbstractMessageSource because the are not relevant. The one you should look into is a SourcePollingChannelAdapter. Exactly this one is that kind of flow beginning endpoint which is similar to MessageProducerSupport. With only the problem that it is based on a periodic scheduled task to request for messages in the provided MessageSource. This type of component is for those protocols which don't provide listening callback, e.g. local file system, (S)FTP, JDBC, MongoDb, POP3, S3 etc.
You probable would expect something similar to MessageSource for the MessageProducer level, but there is not that kind of layer because everything single event-driven protocol has its own specifics, therefore we cannot extract some common abstraction like in case of polling protocols.
If your source system provides for you a reactive Publisher, you don't need to look into a SourcePollingChannelAdapter and MessageSource. You just need a MessageProducerSupport and call its subscribeToPublisher(Publisher<? extends Message<?>> publisher) from the start() implementation.
There is no need in the reactive implementation for the polling since Publisher is not pollable by itself it is event-driven. Although it has its own back-pressure specifics which is out of MessageProducerSupport scope.
There is also some explanation in this section of the doc: https://docs.spring.io/spring-integration/docs/current/reference/html/reactive-streams.html#source-polling-channel-adapter. And see a couple next paragraphs.

non-Controller SpringBoot exception interceptor

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

Detecting disconnects using Spring messaging (websockets / STOMP)

We're using spring-messaging websocket with STOMP. Now we've defined multiple #SubscribeMapping methods, but is there also some sort of callback that gets fired when a client application disconnects from the socket?
We got a list of connect clients and some additional properties, like status. Status field needs to be updated when the client application disconnects.
Any suggestions on how to achieve this in Spring? I've tried implementing ApplicationListener however, there's no usefull information in the OnSessionDisconnect object.

spring-integration (SI), deploy as EAR

I just recently started learning about spring-integration since I need to replace the a MDB(J2EE) application.
The application is composed of mostly MDB which does, splitting, aggregating and scheduling. Which, I think is the perfect criteria to use spring-integration.
I tried out some JMS examples and tried to deploy it but could not figure out how to use the jms-inbound-gateway to replace the MDB.
Is there a way to do this? Or is the only option is still to use MDB and calling the spring-integration service from the MDB's onMessage?
Use a message-driven-channel-adapter instead of an inbound gateway.
With Spring Integration, gateways are for two-way (request/reply) integraton; channel adapters are for one way integration; more like MDBs.
If you need to send some other JMS message downstream, use an outbound channel adapter later in the flow.
It's unusual to keep the MDBs, but you can do it if you really want to, and send a message to an integration flow.

Resources