Related to https://stackoverflow.com/questions/75109345/spring-integration-webflux-inboundgateway-replychannel-for-error-response
The `MessagingGatewaySupport.doSendAndReceiveMessageReactive()` uses `MutableMessageBuilder`
to build a new message for next `send` operation.
Even if this is an error flow, the provided `ErrorMessage` becomes a plain `MutableMessage`.
This may break some downstream logics, like `TracingChannelInterceptor` from Spring Cloud Sleuth,
which checks for the `Message` class to rebuild or reuse a message content.
Therefore, an error handling flow is not able to extract error info because it is just lost.
* Fix `MessagingGatewaySupport.doSendAndReceiveMessageReactive()` to check for message type before
choosing an `AbstractIntegrationMessageBuilder` impl for building a new message.
The regular `MessageBuilder` just builds a new `ErrorMessage` for an exception payload.
* Add `filter()` into a `WebFluxDslTests` error handling flow to be sure that message for
error sub-flow is really an `ErrorMessage`
Fixes https://github.com/spring-projects/spring-integration/issues/3990
Turns out just being on the classpath doesn’t make the type reachable.
If it’s only accessed reflectively then it’s not reachable.
This is exaclt what happened with our `JsonPathUtils` which is used via
reflection from SpEL when that calls its method via function reference
* Change `onReachableType()` logic for `com.jayway.jsonpath.JsonPath` type
to `ClassUtils.isPresent()` on `JsonPathUtils` reflection hint registration.
Currently, when `!resolutionRequired` not resolved channel name
is ignored silently, and we go ahead to `defaultOutputChannel` or
exception thrown
* For better end-user experience `DEBUG` not resolved and ignored channel name if `!resolutionRequired`
* Do not build exception instances in advance
When no `cause` and no clean context of the exception thrown,
the code place where an exception has been created is confusing.
* Fix `SimpleMessageStore` to create an `out of capacity` exception in the
`addMessagesToGroup()` exactly at the point where it is thrown
* Fix `FunctionExpression` and `SupplierExpression` do not pre-create `readOnlyException`:
it is unlikely these kind of expressions are going to be used in the SpEL `write` context,
so we save some time and memory not creating extra object and the plain call `throw new`
gives us a clean context what method call has ended up with such an exception
* * Extract `outOfCapacityException` to the method in the `SimpleMessageStore`
to avoid duplication.
Even if we got in the end extra line in th stack trace, it is still clear from
where it is thrown:
```
org.springframework.messaging.MessagingException: SimpleMessageStore was out of capacity (1) for group 'foo', try constructing it with a larger number.
at org.springframework.integration.store.SimpleMessageStore.outOfCapacityException(SimpleMessageStore.java:324)
at org.springframework.integration.store.SimpleMessageStore.addMessagesToGroup(SimpleMessageStore.java:302)
at org.springframework.integration.store.AbstractMessageGroupStore.addMessageToGroup(AbstractMessageGroupStore.java:189)
at org.springframework.integration.store.SimpleMessageStoreTests.shouldNotHoldMoreThanGroupCapacity(SimpleMessageStoreTests.java:128)
```
* Obtain observed timers in the Integration Graph
The `Observation` populates slightly different Micrometer timer names and their tags
* Fix `MicrometerNodeEnhancer` to search timers in the registry according to the `Observation`
convention if the provided component is observed
* For that purpose expose an `IntegrationManagement.isObserved()` option to check
of component is instrumented with an `Observation`
* Improve the logic in the `IntegrationGraphServer` to delegate into a `Function`
to call `micrometerEnhancer.enhance()` instead of `static` property which might not
be OK in the environment where several integration applications are ran in the same JVM
* * Collect times into graph for inbound gateways & producers
* Fix language in javadoc of new `IntegrationManagement.isObserved()`
* Add `@Nullable` to `MicrometerNodeEnhancer.buildTimerStats()` param to satisfy this method contract
Co-authored-by: Gary Russell <grussell@vmware.com>
Co-authored-by: Gary Russell <grussell@vmware.com>
The time-based tests are very sensitive to an activity on the target machine.
So, strict test sometimes fail.
* Fix `DelayerUsageTests` to deal with approximate values to compare by some percentage
Fixes https://github.com/spring-projects/spring-integration/issues/3953
The replying `MessageHandler` can resolve the target output channel in on-demand manner.
A new messaging annotations on `@Bean` parsing algorithm is missing the lazy-load
opportunity and uses a `RuntimeBeanReference` for output channel options
loading its bean eagerly.
* Fix `AbstractMethodAnnotationPostProcessor` to use a `outputChannelName` and
`defaultOutputChannelName` target properties for channel names to set.
* Expose more reflection hints
* Bring back `@Reflective` on `Pausable` - for possible end-user usage
* Add `ReactiveMessageHandler` hint since its method is used reflectively
in the `IntegrationRSocketMessageHandler`
* Add `@Reflective` on the `ServerRSocketMessageHandler.handleConnectionSetup()`
since it is used reflectively for a `registerHandlerMethod()`
* Add `KafkaRuntimeHints` to expose `Pausable` contract on Kafka inbound endpoints
for SpEL invocation via Control Bus
* Document native images support
* Fix language in docs
Co-authored-by: Gary Russell <grussell@vmware.com>
Co-authored-by: Gary Russell <grussell@vmware.com>
* Also register `Pausable` explicitly and remove its `@Reflective`.
This type is needed for Control Bus SpEL execution, but it might not
be available at runtime because not all endpoints implement it
The `Pausable` & `ManageableSmartLifecycle` types are eligible to be used
from Control Bus.
This one is based on SpEL and therefore requires a reflection for those
types to be available in native image
* GH-3555: Change logger order for errorChannel
Fixes https://github.com/spring-projects/spring-integration/issues/3555
The default global `errorChannel` has a `LoggingHandler` as a subscriber.
It is subscribed without any `order` which may lose logging messages,
when another subscriber with re-throw is present.
* Set default `LoggingHandler` on the default `errorChannel` to `Ordered.LOWEST_PRECEDENCE - 100`
to give a room for custom subscribers without an `order` and still get error logged
* Add extra note in docs about an order for custom subcribers
Co-authored-by: Gary Russell <grussell@vmware.com>
Co-authored-by: Gary Russell <grussell@vmware.com>
* GH-3946: Revise Router channelKeyFallback option
Fixes https://github.com/spring-projects/spring-integration/issues/3946
The `AbstractMappingMessageRouter` has both `resolutionRequired` and `channelKeyFallback`
as `true` by default.
End-users expects them to back off when they set a `defaultOutputChannel`.
They really want something similar to Java `switch` statement
* Change the logic in the `AbstractMappingMessageRouter` to reset `channelKeyFallback`
to `false` when `defaultOutputChannel` to avoid attempts to resolve channel from name,
but rather fallback to `defaultOutputChannel` as it states from th mentioned
Java `switch` statement experience
* Deprecate `RouterSpec.noChannelKeyFallback()` in favor of newly introduced `channelKeyFallback(boolean)`
* Call `channelKeyFallback(false)` from an overloaded `defaultOutputToParentFlow()`
to reflect the mentioned expected behavior in Java DSL as well.
* Respectively, deprecate `KotlinRouterSpec.noChannelKeyFallback()` wrapper
in favor of newly introduced `channelKeyFallback(channelKeyFallback: Boolean)`
* Remove redundant already `noChannelKeyFallback()` option in the `NoFallbackAllowedTests`
* Document the change and new behavior
* Fix `IntegrationGraphServerTests` to `setChannelKeyFallback(true)` explicitly
* Remove not relevant `default-output-channel` from the `DynamicRouterTests-context.xml`
* Reject an `AbstractMappingMessageRouter` configuration where `defaultOutputChannel` is provided
and both `channelKeyFallback` & `resolutionRequired` are set to `true`.
Such a state makes `defaultOutputChannel` as not reachable and may cause some confusions in target
applications.
* Remove `&` symbol from JavaDocs
* Fix `boolean` expression for `AbstractMappingMessageRouter` configuration check
* Fix `IntegrationGraphServerTests` for new router behavior
* Improve language in docs
The `GatewayProxyInitializationAotProcessor` uses mistakenly a `ProxyFactoryBean` type
instead of an expected `GatewayProxyFactoryBean`.
Looks like we don't need to scan for interfaces since they are properly transformed
to the `AnnotationGatewayProxyFactoryBean` bean definition during AOT phase
* GH-3945: Fix `not eligible for getting processed`
Fixes https://github.com/spring-projects/spring-integration/issues/3945
The `IntegrationManagementConfiguration` produces an `IntegrationManagementConfigurer` which is a `BeanPostProcessor`.
According to Spring recommendation this kind of infrastructure beans must be declared as `static`.
Due to an `implements ImportAware, EnvironmentAware` nature of the `IntegrationManagementConfiguration`,
we cannot use `static @Bean` method.
But since the `IntegrationManagementConfiguration` is not involved in any bean post-processing,
it is safe to follow recommendation and mark it as a `@Role(BeanDefinition.ROLE_INFRASTRUCTURE)`.
* Fix `MessagePublishingInterceptor` to initialize `MessagingTemplate` and `DestinationResolver` lazily
* Fix `AbstractMethodAnnotationPostProcessor` to initialize `DestinationResolver` lazily
**Cherry-pick to `5.5.x`**
* * Use `getChannelResolver()` internally in the `AbstractMethodAnnotationPostProcessor`
instead of direct property access which might not be initialized yet
* Use a plain `boolean` for `templateInitialized` in the `MessagePublishingInterceptor`
to avoid skips in other thread where and move on with still not initialized properties
* * Remove unused import
* * Fix `this.` prefix for `beanFactory` property reference
* Add observation for message channels
* Add observation for message channels
The `MessageChannel.send()` is, essentially, only the point in Spring Integration where we produce a message
and can emit a `PRODUCER` kind span.
* Implement `IntegrationObservation.PRODUCER` infrastructure based on the `MessageSenderContext`
* Implement an observation emission in the `AbstractMessageChannel` based on the mentioned `IntegrationObservation.PRODUCER`
* Build a `MutableMessage.of(message)` to be able to modify message header in the `MessageSenderContext` via tracer `Propagator`
or other tracing injection instrument
* Document which components are instrumented with an `ObservationRegistry`
* Fix language in docs
Co-authored-by: Gary Russell <grussell@vmware.com>
Co-authored-by: Gary Russell <grussell@vmware.com>
Turns out the AOT engine deals only with indexed constructor arguments for bean definition
* Rework `GatewayProxyInstantiationPostProcessor.processAheadOfTime()`
to populate a service interface type as an indexed ctor argument instead of generic one
Fixes https://github.com/spring-projects/spring-integration/issues/3686
* Add `src/idea` with respective editor config for IntelliJ IDEA.
Must be imported into an IDE
* Add `src/eclipse` with respective editor config for Eclipse/STS
* Reformat imports in source code according a new editor config
The `GatewayProxyInstantiationPostProcessor` does nothing on the AOT phase.
Therefore, scanned and imported beans for `@MessagingGateway` are not decorated
after AOT
* Implement a `BeanRegistrationAotProcessor` in the `GatewayProxyInstantiationPostProcessor`
to `RegisteredBean.getMergedBeanDefinition()` withe respective `AnnotationGatewayProxyFactoryBean`
and its requirements for ctor arg and `targetType`
* Scan for the `@MessagingGateway` bean in the `GatewayProxyInitializationAotProcessor`
to register respective proxy hints
The SF now understands `targetType` on a `BeanDefinition` for `FactoryBean`
* Remove `FactoryBean.OBJECT_TYPE_ATTRIBUTE` from the `GatewayParser`
* Expose `targetType` on a bean definition for an `AnnotationGatewayProxyFactoryBean`
in the `IntegrationFlowBeanPostProcessor` for DSL definitions
* GH-3903: Improve AOT for gateway proxy beans
Fixes https://github.com/spring-projects/spring-integration/issues/3903
* Fix `MessagingGatewayRegistrar` to set a `targetType` on the bean definition
instead of `FactoryBean.OBJECT_TYPE_ATTRIBUTE`
* Rework `GatewayProxyBeanRegistrationAotProcessor` to the
`GatewayProxyInitializationAotProcessor implements BeanFactoryInitializationAotProcessor`
to avoid custom code generation
* Remove tests which rely on the `FactoryBean.OBJECT_TYPE_ATTRIBUTE`
* * Add `setBeanClass(GatewayProxyFactoryBean.class)` to satisfy Spring container expectations
* * Rework `GatewayProxyInitializationAotProcessor` to deal with generics
we are exposing now on the `ProxyFactoryBean`
To avoid duplication for scanning register a `IntegrationComponentScanRegistrar`
as a bean by itself and check for its presence before scanning
* Exclude this bean definition from the AOT since its logic has already passed on AOT generation
and we don't need this bean at runtime any more
* Some code style improvement for SMB classes
* Make an `SmbSessionTests` based on the `SmbTestSupport` for faster execution, but not blocking on fake URL connection attempt
* Remove `AbstractMqttMessageDrivenChannelAdapter.Topic` model in favor of `LinkedHashMap` handling
* Fix gateway proxy for generic interface in XML
Without a `FactoryBean.OBJECT_TYPE_ATTRIBUTE` the application context cannot determine a qualified
with generic an interface injection
* Set back `FactoryBean.OBJECT_TYPE_ATTRIBUTE` in the `GatewayParser`
when not in AOT mode.
Set a `targetType` when used in AOT
* * Remove unused import
* * Fix `GatewayParserTests` for new code base
* Add observation to inbound endpoints
* * Improve `Observation` logic in the `MessageProducerSupport` and `MessagingGatewaySupport`
* Clean up Javadocs in observation support classes
* Add test for `MessagingGatewaySupport` instrumentation into `IntegrationObservabilityZipkinTests`
* Add docs for `@EnableIntegrationManagement.observationPatterns()`
* The generated docs for metrics and spans looks OK: have both `Gateway` and `Handler` section now
* * Fix Checkstyle violations
* * Fix `IntegrationMBeanExporter` to filter out a `MessageProducer` from sources.
Marking a `MessageProducerSupport` with an `IntegrationInboundManagement`
causes it to be considered as a source for JMX.
Technically it might have a reason since it is indeed a source, but that's fully different story
* * No observation instrumentation by default
* * Fix "no observation by default" configuration logic