-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Add a basic example to Spring Integration with Reactive Streams #3718
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I've seen that there is no clear example of how to quickly get started with Spring Integration and Reactive Streams. This PR tries to help with this.
|
@migroskub Please sign the Contributor License Agreement! Click here to manually synchronize the status of this Pull Request. See the FAQ for frequently asked questions. |
|
@migroskub Thank you for signing the Contributor License Agreement! |
artembilan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for a sample!
Please, consider to move it before A reactive outbound channel adapter paragraph.
Any samples for the outbound part?
The R2dbcMessageHandler should be a good one took into.
|
Gentle ping. Thank you! |
|
I've committed the changes as you've suggested. I have 3 notes after reading some pages from the documentation.
|
|
Thank you for feedback, @migroskub !
|
artembilan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
| } | ||
| ``` | ||
|
|
||
| And now we will be able to use it: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this flow sample belongs to the producer section above.
The CustomReactiveMessageHandler deserves its own independent usage sample.
Otherwise it is confusing a little bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be resolved
|
|
||
| @Override | ||
| protected Mono<Void> handleMessageInternal(Message<?> message) { | ||
| return Mono.fromSupplier(() -> this.queryTypeExpression.getValue(this.evaluationContext, message, Type.class)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@artembilan I'm struggling with the CustomReactiveMessageHandler implementation - can you simplify this to a more basic supplier usage that will be practical and won't require evaluationContext?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just do -> message.getHeaders().get("queryType", Type.class).
And no queryTypeExpression in the code at all!
| A returned reactive type can be subscribed immediately if we are in one-way, fire-and-forget scenario, or it is propagated downstream (request-reply scenarios) for further integration flow or an explicit subscription in the target business logic, but still downstream preserving reactive streams semantics. | ||
| An example for a reactive inbound channel adapter: | ||
| ```java | ||
| public class CustomReactiveMessageSource extends MessageProducerSupport { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not correct to call it MessageSource. Just because it does not implement a MessageSource. And definitely a reactive publisher could not be wrapped to the MessageSource anyway.
Better to call it CustomReactiveMessageProducer since you really do it correctly extending MessageProducerSupport and using its subscribeToPublisher() from the doStart() impl.
|
|
||
| private final CustomReactiveSource customReactiveSource; | ||
|
|
||
| public CustomReactiveSourceMessageProducer(CustomReactiveSource customReactiveSource) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that constructor for the class you called properly. So, please, revise the name of the class 😄
|
|
||
| @Override | ||
| protected Mono<Void> handleMessageInternal(Message<?> message) { | ||
| return Mono.fromSupplier(() -> this.queryTypeExpression.getValue(this.evaluationContext, message, Type.class)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just do -> message.getHeaders().get("queryType", Type.class).
And no queryTypeExpression in the code at all!
…e fix and queryTypeExpression removement
| MessageBuilder | ||
| .withPayload(event.getBody()) | ||
| .setHeader(MyReactiveHeaders.SOURCE_NAME, event.getSourceName()) | ||
| .build());) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ; is wrong here.
I would prefer to have this Flux extracted as a variable. It's OK to have it in this bean method definition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean like this?
public class MainFlow {
@Bean
public IntegrationFlow buildFlow() {
Flux<Message<?>> myFlux = this.customReactiveSource
.map(event - >
MessageBuilder
.withPayload(event.getBody())
.setHeader(MyReactiveHeaders.SOURCE_NAME, event.getSourceName())
.build());
return IntegrationFlows.from(myFlux)
.handle(outputChannel)
.get();
}
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep! This is good. It does give us a clue what is that customReactiveSource about and which from() factory is going to be for building an IntegrationFlow.
|
I think the PR is ready |
|
|
||
| @Override | ||
| protected void doStart() { | ||
| Flux<Message<<?>> messageFlux = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo for diamond definition. Has lead to this error:
Execution failed for task ':checkAsciidocLinks'.
> [*** Anchor reference errors found:,
Anchor '?' not found in 'reactive-streams.adoc', if in another file, it needs to be qualified with './fileName.adoc#']
But originally I definitely have missed it 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't exactly understood this. What should be fixed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is wrong: Flux<Message<<?>>.
Must be Flux<Message<?>>. You have to have exact number of closing bracket as many as you have opening.
The error is misleading, but it really helped me to spot the typo in your code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
|
|
||
| @Override | ||
| protected void doStart() { | ||
| Flux<Message<<?>> messageFlux = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is wrong: Flux<Message<<?>>.
Must be Flux<Message<?>>. You have to have exact number of closing bracket as many as you have opening.
The error is misleading, but it really helped me to spot the typo in your code.
|
Thank you, @migroskub; looking forward for more! |
I've seen that there is no clear example of how to quickly get started with Spring Integration and Reactive Streams. This PR tries to help with this.
I'm trying to help mainly for questions like this.