bennidi / mbassador

Powerful event-bus optimized for high throughput in multi-threaded applications. Features: Sync and Async event publication, weak/strong references, event filtering, annotation driven
MIT License
955 stars 146 forks source link

Post last message to new subsciber #85

Closed potmo closed 9 years ago

potmo commented 9 years ago

Is it possible (doesn't seem so from the code) to post a message to a newly subscribing handler? What I'd like to do is to post the last message of a type when a new handler is subscribing. Something like this:

bus.subscribe(handlerA); // nothing posted
bus.post(data).asynchronously(); // posting to handlerA
bus.subscribe(handlerB); // data posted to handlerB
bus.post(data).asynchronously(); // posting to handlerA and handlerB
bennidi commented 9 years ago

No, this is not possible. What is it that you are trying to achieve?

potmo commented 9 years ago

I have a couple of views in an Android app that I want to populate with data from HTTP requests. When I add a new view (they are something like widgets) in runtime I want that view to get the latest data that the view just subscribed to.

potmo commented 9 years ago

For me it would actually be sufficient to be able to post a message to a single subscriber. Something like bus.post(data).to(oneSubscriber).asynchronously() Maybe this will bloat the interfaces a bit but for me it would be nice. Would you take a PR on that?

bennidi commented 9 years ago

I think you should have a look at the Mbassador Spring component. They way that the transactional message publication is implemented there is pretty much how I would recommend you to go about for your requirement. But I won't accept a PR on that feature because it is easily custom made and I am not convinced it is a way that many users will (and should) use the bus.

potmo commented 9 years ago

Thanks. I'll have a look at the Spring component. It makes sense that this might not be the best thing to add to the main branch.

potmo commented 9 years ago

If someone is interested you can do something like this to also post a message to the subscribing listener (only) when you subscribe it.

package se.springworks.messagebus;

import net.engio.mbassy.bus.MBassador;
import net.engio.mbassy.bus.MessagePublication;
import net.engio.mbassy.bus.publication.SyncAsyncPostCommand;
import net.engio.mbassy.subscription.Subscription;

import java.util.Collection;
import java.util.LinkedList;

public class SubscriptionPostingMBassador<T> extends MBassador<T> {

  public void subscribe(Object listener, T message) {
    super.subscribe(listener);

    MessagePublication.Factory publicationFactory = getPublicationFactory();

    Collection<Subscription> listenerSubscriptions;
    listenerSubscriptions = getMessageSubscriptionsForListener(listener, message);

    MessagePublication publication;
    publication = publicationFactory.createPublication(getRuntime(),
                                                       listenerSubscriptions,
                                                       message);

    addAsynchronousPublication(publication);
  }

  private Collection<Subscription> getMessageSubscriptionsForListener(final Object listener,
                                                                      final T message) {
    Collection<Subscription> subscriptions = getSubscriptionsByMessageType(message.getClass());
    Collection<Subscription> listenerSubscriptions = new LinkedList<>();

    for (Subscription subscription : subscriptions) {
      if (subscription.contains(listener)) {
        listenerSubscriptions.add(subscription);
      }
    }
    return listenerSubscriptions;
  }
}