How to Create MassTransit Message Interceptor (Observer) with Scoped Lifetime - masstransit

We can setup Consume Observer using following way
busControl.ConnectConsumeObserver(container.GetInstance<MessageConsumerInterceptor>());
I want to apply Scope lifestyle to MessageConsumerInterceptor so that I can fill/ initialize some object before consuming or handling the message. And I can access that filled object through the message handler or consumer. Now how I can achieve this using MassTransit?
I am expecting your help or possible suggestion.
Thanks in advance.

Observer is a not good candidate for this. Observers only observe, they should not change any state or have effect on message processing.
What you are looking at is a middleware.
Check this documentation page on how to create and apply custom middleware.
You will get the ConsumeContext as the Send method parameter in your filter and there you can use methods GetOrAddPayload<T> and TryGetPayload to add something to the context, so you can fetch this data later inside your consumer.

Related

Axon How can I add an event listener/interceptor to intercept events before they reach their handlers?

I have a projection class (to build a read model) and I want to add an interceptor for its events in a way that if the id passed in the event leads to a null object (non-existent in my db) then I want to block it, otherwise let it pass.
This way I will escape adding a null checker on EVERY event handler.
#EventHandler
public void onEvent(Event event) {
Entity entity = getEntity(event.getId());
if(entity!=null){ // what I don't want to add on every event handler
dostuff();
}
}
I found that axon provides an interface called EventListener but I'm not sure how to work with it and I'm not sure if this will be intercepting ALL of my events or if I will be able to intercept select events.
There is no mention anywhere for this interface but in the official documentation (with no actual examples or so)
You are right on the part the the Reference Guide still needs some improvements #bleh10 - I can assure you, they're being worked on, the team is just spread out relatively thin.
In absence of the sought after example, I think I can give you some guidance.
What you're looking for is a MessageHandlerInterceptor implementation, specifically for the EventMessage type. As the naming suggests, it intercepts messages prior to being handled, which corresponds perfectly with the question you've posed.
Secondly, you obviously need a place to configure these. Within an Axon application, the technical aspect of delivering events to your #EventHandler annotated methods, is the Event Processor. As such, it is in charge of ensuring the Event Messages flowing through it are intercepted as desired.
Hence, the place to configure your EventMessage MessageHandlerInterceptor, is on the EventProcessor implementation you've chosen. To ensure a given Event Handling Component is set in a specific EventProcessor, you can specify it's Processing Group by annotating the class with the #ProcessingGroup annotation.
From there on, you can easily configure specific properties for your Event Processor by utilizing the EventProcessingConfigurer. More specifically, I'd suggest to use the EventProcessingConfigurer#registerHandlerInterceptor(String, Function<Configuration, MessageHandlerInterceptor<? super EventMessage<?>>>) method for this.
The first String parameter is meant to describe the name of your Processing Group. The second is a Function which receive the Axon Configuration and should output a MessageHandlerInterceptor which can deal with the EventMessage class.
Hope this helps you out!

why does spring cloud stream's #InboundChannelAdapter accept no parameters?

I'm trying to use spring cloud stream to send and receive messages on kafka. The examples for this use a simple example of using time stamps as the messages. I'm trying to go just one step further into a real world application when I ran into this blocker on the InboundChannelAdapter docs:
"A method annotated with #InboundChannelAdapter can't accept any parameters"
I was trying to use it like so:
#InboundChannelAdapter(value = ChannelManager.OUTPUT)
public EventCreated createCustomerEvent(String customerId, String thingId) {
return new EventCreated(customerId, thingId);
}
What usage am I missing? I imagine that when you want to create an event, you have some data that you want to use for that event, and so you would normally pass that data in via parameters. But "A method annotated with #InboundChannelAdapter can't accept any parameters". So how are you supposed to use this?
I understand that #InboundChannelAdapter comes from spring-integration, which spring-cloud-stream extends, and so spring-integration may have a different context in which this makes sense. But it seems un-intuitive to me (as does using an _INBOUND_ChannelAdapter for an output/producer/source)
Well, first of all the #InboundChannelAdapter is defined exactly in Spring Integration and Spring Cloud Stream doesn't extend it. That's false. Not sure where you have picked up that info...
This annotation builds something like SourcePollingChannelAdapter which provides a poller based on the scheduler and calls periodically a MessageSource.receive(). Since there is no any context and end-user can't effect that poller's behavior with his own arguments, the requirement for empty method parameters is obvious.
This #InboundChannelAdapter is a beginning of the flow and it is active. It does its logic on background without your events.
If you would like to call some method with parameters and trigger with that some flow, you should consider to use #MessagingGateway: http://docs.spring.io/spring-integration/reference/html/messaging-endpoints-chapter.html#messaging-gateway-annotation
How are you expecting to call that method? I think there was a miscommunication with your statement "stream extends integration" and Artem probably understood that we extend #InboundChannelAdatper
So, if you are actively calling this method, as it appears since you do have arguments that are passed to it, why not just using your source channel to send the data?
Usually sources do not require arguments as they are either push like the twitter stream that taps on twitter, listen for events and pushes them to the source channel, or they are polled, in which case, they are invoked on an interval defined via a poller.
As Artem pointed, if your intention is to call this method from your business flow, and deal with the return while triggering a message flow, then check his link from the docs.

Spring AMQP: When using programmatic endpoint registration, how to set routing key?

I am using programmatic endpoint registration of listener endpoints:
MethodRabbitListenerEndpoint endpoint = new MethodRabbitListenerEndpoint();
endpoint.setId(endpointId);
endpoint.setQueues(eventsQueue);
endpoint.setBean(hanlderMethod.bean);
endpoint.setMethod(hanlderMethod.method);
endpoint.setMessageHandlerMethodFactory(messageHandlerMethodFactory);
registrar.registerEndpoint(endpoint);
My question is, how do I determine the routing key for this endpoint?
Edit: To further clarify, I am using a single queue for different types of messages, and I want to route them to different methods based on the routing key. This is in addition to the routing key used to route the messages to this queue to begin with.
Basically the use case is a general-purpose events bus. All the events go to the same exchange. Each type of event has a unique routing key. Each service has an events queue. Each service subscribes to the events it is interested in by adding the appropriate binding between the events exchange and its own events queue using the routing key for that event type. Each event type has a different handler method.
Look, you say Listener, so you are going to listen some queue for messages.
And right, you do that via setQueues().
Now regarding routingKey:
The routing key is a message attribute. The exchange might look at this key when deciding how to route the message to queues (depending on exchange type).
So, it really doesn't relate to the Listener.
Although I agree that we should declare Binding exactly in that place when we deal with queue. Therefore in the listener part.
So, if you do MethodRabbitListenerEndpoint registration manually (bypassing #RabbitListener definitions), you should declare and register Binding manually, too. And already here with an appropriate routingKey: http://docs.spring.io/spring-amqp/reference/html/_reference.html#_binding
UPDATE
There is no such a built-in feature which you are looking for.
We have MultiMethodRabbitListenerEndpoint who does the routing based on the payload type, but not any other possible filter.
What you want can be achieved with the Spring Integration router which can make the decision based on the AmqpHeaders.RECEIVED_ROUTING_KEY header.
From other side maybe that would be better to register unique queues for each routing key and have only one possible listener for that queue with appropriate method.

How to use Reactor to dispatch events to multiple consumers and to filter events based on event data?

I'm evaluating Reactor (https://github.com/reactor/reactor) if it would be suitable for creating an event dispatching framework inside my Spring / enterprise application.
First, consider a scenario in which you have an interface A and concrete event classes B, C, and so on. I want to dispatch concrete events to multiple consumers i.e. observers. Those are registered to a global Reactor instance during bean post processing. However, you can register them dynamically. In most cases there is one producer sending events to multiple consumers at high rate.
I have used Selectors, namely, the ClassSelector to dispatch the correct event types to the correct consumers. This seems to work nicely.
Reactor reactor = ...
B event = ...
Consumer<Event<B>> consumer = ...
// Registration is used to cancel the subscription later
Registration<?> registration = reactor.on(T(event.getClass()), consumer);
To notify, use the type of the event as a key
B event = ...
reactor.notify(event.getClass(), Event.wrap(event));
However, I'm wondering if this is the suggested way to dispatch events efficiently?
Secondly, I was wondering that is it possible to filter events based on the event data? If I understand correctly, Selectors are only for inspecting the key. I'm not referring to event headers here but to the domain specific object properties. I was wondering of using Streams and Stream.filter(Predicate<T> p) for this but is it also possible to filter using Reactor and Selectors? Of course I could write a delegating consumer that inspects the data and delegates it to registered consumers if needed.
There is a helper object called Selectors that helps to create the various kinds of built-in Selector implementations. There you can see references to the PredicateSelector. The PredicateSelector is very useful as it allows you complete control over the matching of the notification key. It can be a Spring #Bean, an anonymous inner class, a lambda, or anything else conforming to the simple Predicate interface.
Optionally, if you have the JsonPath library in your classpath, then you can use the JsonPathSelector to match based on JsonPath queries.
In either of these cases you don't need to have a separate object for a key if the important data is actually the domain object itself. Just notify on the object and pass the Event<Object> as the second parameter.
MyPojo p = service.next();
reactor.notify(p, Event.wrap(p));

what is the difference between event listerners and subscribers in symfony2 [duplicate]

I'm working in the Symfony2 framework and wondering when would one use a Doctrine subscriber versus a listener. Doctrine's documentation for listeners is very clear, however subscribers are rather glossed over. Symfony's cookbook entry is similar.
From my point of view, there is only one major difference:
The Listener is signed up specifying the events on which it listens.
The Subscriber has a method telling the dispatcher what events it is listening to
This might not seem like a big difference, but if you think about it, there are some cases when you want to use one over the other:
You can assign one listener to many dispatchers with different events, as they are set at registration time. You only need to make sure every method is in place in the listener
You can change the events a subscriber is registered for at runtime and even after registering the subscriber by changing the return value of getSubscribedEvents (Think about a time where you listen to a very noisy event and you only want to execute something one time)
There might be other differences I'm not aware of though!
Don't know whether it is done accidentally or intentionally.. But subscribers have higher priority that listeners - https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php#L73-L98
From doctrine side, it doesn't care what it is (listener or subscriber), eventually both are registered as listeners - https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/EventManager.php#L137-L140
This is what I spotted.
You should use event subscriber when you want to deal with multiple events in one class, for example in this symfony2 doc page article, one may notice that event listener can only manage one event, but lets say you want to deal with several events for one entity, prePersist, preUpdate, postPersist etc... if you use event listener you would have to code several event listener, one for each event, but if you go with event subscriber you just have to code one class the event susbcriber, look that with the event subscriber you can manage more than one event in one class, well thats the way i use it, i preffer to code focused in what the model business need, one example of this may be went you want to handle several lifecycle events globaly only for a group of your entities, to do that you can code a parent class and defined those global methods in it, then make your entities inherit that class and later in your event susbcriber you subscribe every event you want, prePersist, preUpdate, postPersist etc... and then ask for that parent class and execute those global methods.
Another important thing: Doctrine EventSubscribers do not allow you to set a priority.
Read more on this issue here
Both allow you to execute something on a particular event pre / post persist etc.
However listeners only allow you to execute behaviours encapsulated within your Entity. So an example might be updating a "date_edited" timestamp.
If you need to move outside the context of your Entity, then you'll need a subscriber. A good example might be for calling an external API, or if you need to use / inspect data not directly related to your Entity.
Here is what the doc is saying about that in 4.1.
As this is globally applied to events, I suppose it's also valid for Doctrine (not 100% sure).
Listeners or Subscribers
Listeners and subscribers can be used in the same application indistinctly. The decision to use either of them is usually a matter
of personal taste. However, there are some minor advantages for each
of them:
Subscribers are easier to reuse because the knowledge of the events is kept in the class rather than in the service definition.
This is
the reason why Symfony uses subscribers internally;
Listeners are more flexible because bundles can enable or disable each of them conditionally depending on some configuration value.
http://symfony.com/doc/master/event_dispatcher.html#listeners-or-subscribers
From the documentation :
The most common way to listen to an event is to register an event
listener with the dispatcher. This listener can listen to one or more
events and is notified each time those events are dispatched.
Another way to listen to events is via an event subscriber. An event
subscriber is a PHP class that's able to tell the dispatcher exactly
which events it should subscribe to. It implements the
EventSubscriberInterface interface, which requires a single static
method called getSubscribedEvents().
See the example here :
https://symfony.com/doc/3.3/components/event_dispatcher.html

Resources