-
Notifications
You must be signed in to change notification settings - Fork 16
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
Publish events to Spring Cloud Stream channels #5
base: master
Are you sure you want to change the base?
Publish events to Spring Cloud Stream channels #5
Conversation
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.
Potentially this can be valuable extension.
I'm not sure if this is the right place for it. Maybe, it can be in a dedicated Github Repo.
It would be great if we could try other binders, like Kafka for example. I'm afraid that Spring Cloud Stream is not allowing to programmatically set the seek
/offset
at the moment. This implies that we will not be able to utilize Axon StreamableMessageSource
and Tracking processors to scale better.
...xonframework/extensions/springcloud/eventhandling/processor/AxonProcessorMessageHandler.java
Outdated
Show resolved
Hide resolved
...xonframework/extensions/springcloud/eventhandling/processor/AxonProcessorMessageHandler.java
Outdated
Show resolved
Hide resolved
...xonframework/extensions/springcloud/eventhandling/processor/AxonProcessorMessageHandler.java
Outdated
Show resolved
Hide resolved
@mehdichitforoosh, are you up for adjusting your PR towards a different format? In essence, this extension has been set up to tap into Spring Cloud Discovery for Command Message distribution. That would thus opt for the current code to be moved to an |
Hi @smcvb. |
That's amazing to hear @mehdichitforoosh!
|
Ok dear Steven @smcvb |
Merge from original repo
Conflicts: pom.xml
dear @smcvb |
Thanks for the effort so far @mehdichitforoosh, much appreciated.
Likely there are more fine-grained comments to go over too, but let's first take a stab at the above. |
Thanks @smcvb for your attention. |
Add Javadocs,copyright Add builder for creating objects
Hi Steven @smcvb
|
this.messageSource = builder.messageSource; | ||
this.converter = builder.converter; | ||
if (builder.eventBus != null) { | ||
this.messageProcessors.addAll(singletonList(builder.eventBus::publish)); |
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 wonder if we should add EventBus by default here? @smcvb what do you think? In my opinion, we could leave this decision to the users of the API, but I am afraid that in that case, we are missing something like MultiSubscribableMessageSource.java
allowing them to subscribe to multiple sources: eventBus/eventStore, streamSource, ...
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.
Honestly, I think this is a bad idea.
As you point @idugalic, we should have a form of MultiSubscribableMessageSource
.
Simply publishing the Spring Messages as new events on the local EventBus
is very likely going to cause a lot of issues.
Let alone that it leaks the concerns of another service's Events into the domain connecting to it.
Hi @mehdichitforoosh. Thank you for this PR. Much appreciated! Conceptually this looks very good! It is important to note that this extension module is supporting |
Hi @idugalic Thank you for your comments. |
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.
For now, I will not proceed with the integration tests yet.
Got a bunch of comments here, lots about JavaDoc. My main concerns are the usage of the EventBus
in the message source directly and the seeming duplication with the SpringStreamMessageProcessor
and SpringStreamMessageSource
And, I shouldn't forget to extend my apologies for the late review.
Times have been hectic here @mehdichiforoosh, and sadly there weren't a lot of people we could spare on the other subjects we're working on.
I hope this review doesn't come too late for you..`
pom.xml
Outdated
|
||
<spring.version>5.3.4</spring.version> | ||
<spring-messaging.version>5.3.4</spring-messaging.version> |
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.
Is there an actual need to have a separate spring-messaging
and spring-integration
property, or could we tag along with spring.version
?
@@ -0,0 +1,100 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- | |||
~ Copyright (c) 2010-2020. Axon Framework |
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 notice should extend to 2021, as this commit is from 2021.
* @author Mehdi chitforoosh | ||
* @since 4.5 | ||
*/ | ||
public class SpringStreamMessageProcessor extends AbstractMessageProducingHandler implements SubscribableMessageSource<EventMessage<?>> { |
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.
Could we call it the SpringStreamMessageSource
instead of the SpringStreamMessageProcessor
?
Calling it a processor to closely aligns with Axon's Event Processor logic.
Hence, I assume it will confuse users.
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.
Alright, I notice there already is a SpringStreamMessageSource
. On top of that, it also extends the AbstractMessageProducingHandler
class and implements the SubscribableMessageSource
.
Would you mind explaining why both exist in this pull request?
import java.util.Optional; | ||
|
||
/** | ||
* Interface describing a mechanism that converts Spring Messages from an Axon Messages and vice versa. |
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.
* Interface describing a mechanism that converts Spring Messages from an Axon Messages and vice versa. | |
* Interface describing a mechanism that converts a Spring {@code org.springframework.messaging.Message} from an Axon {@link org.axonframework.eventhandling.EventMessage} and vice versa. |
public interface SpringMessageConverter { | ||
|
||
/** | ||
* Creates an Spring Message from given {@code eventMessage}. |
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.
* Creates an Spring Message from given {@code eventMessage}. | |
* Creates a Spring {@code org.springframework.messaging.Message} from the given {@code eventMessage}. |
/** | ||
* Instantiate a {@link SpringStreamMessageSource} based on the fields contained in the {@link SpringStreamMessageSource.Builder}. | ||
* The {@link EventBus} is a <b>hard requirement</b> and thus should be provided. | ||
* The {@link SpringMessageConverter} is a <b>hard requirement</b> and thus should be provided. | ||
* <p> | ||
* Will validate that the {@link EventBus} and {@link SpringMessageConverter} are not {@code null}, and will throw an | ||
* {@link AxonConfigurationException} if for either of them this holds. | ||
* | ||
* @param builder the {@link SpringStreamMessageSource.Builder} used to instantiate a {@link SpringStreamMessageSource} instance | ||
*/ | ||
protected SpringStreamMessageSource(SpringStreamMessageSource.Builder builder) { |
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.
Since the builder is an inner class, you do not have to define the root class in the JavaDoc too:
/** | |
* Instantiate a {@link SpringStreamMessageSource} based on the fields contained in the {@link SpringStreamMessageSource.Builder}. | |
* The {@link EventBus} is a <b>hard requirement</b> and thus should be provided. | |
* The {@link SpringMessageConverter} is a <b>hard requirement</b> and thus should be provided. | |
* <p> | |
* Will validate that the {@link EventBus} and {@link SpringMessageConverter} are not {@code null}, and will throw an | |
* {@link AxonConfigurationException} if for either of them this holds. | |
* | |
* @param builder the {@link SpringStreamMessageSource.Builder} used to instantiate a {@link SpringStreamMessageSource} instance | |
*/ | |
protected SpringStreamMessageSource(SpringStreamMessageSource.Builder builder) { | |
/** | |
* Instantiate a {@link SpringStreamMessageSource} based on the fields contained in the {@link Builder}. | |
* <p> | |
* Will validate that the {@link SpringMessageConverter} is not {@code null}, and will throw an | |
* {@link AxonConfigurationException} if for either of them this holds. | |
* | |
* @param builder the {@link Builder} used to instantiate a {@link SpringStreamMessageSource} instance | |
*/ | |
protected SpringStreamMessageSource(Builder builder) { |
*/ | ||
public class SpringStreamMessageSource extends AbstractMessageProducingHandler implements SubscribableMessageSource<EventMessage<?>> { | ||
|
||
private final CopyOnWriteArrayList<Consumer<List<? extends EventMessage<?>>>> messageProcessors = new CopyOnWriteArrayList<>(); |
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 it's better to call these eventProcessors
as they are consumers of the EventMessage
type.
Optional<EventMessage<?>> optional = converter.readSpringMessage(message); | ||
optional.ifPresent(eventMessage -> { |
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.
Nit: Why not chain the outcome of the converter
directly with the ifPresent
invocation?
* @param eventBus The messageSource to subscribe | ||
* @return the current Builder instance, for fluent interfacing | ||
*/ | ||
public SpringStreamMessageSource.Builder eventBus(EventBus eventBus) { |
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 we can remove the EventBus
from the builder, as described earlier in the constructor.
* @param converter The converter to convert messages | ||
* @return the current Builder instance, for fluent interfacing | ||
*/ | ||
public SpringStreamMessageSource.Builder converter(SpringMessageConverter converter) { |
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.
As we're in the Builder
here, we do not have to define the root class:
public SpringStreamMessageSource.Builder converter(SpringMessageConverter converter) { | |
public Builder converter(SpringMessageConverter converter) { |
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.
@smcvb No Problem.
Thank you for your reviews.
I'll check your comments and commit again in a few days.
Good luck.
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.
Sure thing @mehdichitforoosh! I'll aim to get you an earlier follow-up review this time around 👍
We can integrate Axon
EventBus
with Spring Integration and Spring Cloud Stream with these configurations.As a Message Producer:
As a Consumer:
Sink.INPUT
andSource.OUTPUT
areMessageChannel
s from Spring Cloud Stream.