introduced specialized subscriptions for better performance and customization options
This commit is contained in:
parent
08f6e45c7c
commit
014f22df9e
104
src/main/java/org/mbassy/subscription/Subscription.java
Normal file
104
src/main/java/org/mbassy/subscription/Subscription.java
Normal file
|
@ -0,0 +1,104 @@
|
|||
package org.mbassy.subscription;
|
||||
|
||||
import org.mbassy.IMessageBus;
|
||||
import org.mbassy.IPublicationErrorHandler;
|
||||
import org.mbassy.common.ConcurrentSet;
|
||||
import org.mbassy.PublicationError;
|
||||
import org.mbassy.listener.MessageHandlerMetadata;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Subscription is a thread safe container for objects that contain message handlers
|
||||
*/
|
||||
public abstract class Subscription {
|
||||
|
||||
private final Method handler;
|
||||
|
||||
protected ConcurrentSet<Object> listeners = new ConcurrentSet<Object>();
|
||||
|
||||
private int priority = 0;
|
||||
|
||||
private IMessageBus owningBus ;
|
||||
|
||||
public Subscription(IMessageBus owningBus, MessageHandlerMetadata messageHandler) {
|
||||
this.owningBus = owningBus;
|
||||
this.priority = messageHandler.getPriority();
|
||||
this.handler = messageHandler.getHandler();
|
||||
this.handler.setAccessible(true);
|
||||
}
|
||||
|
||||
public abstract void publish(Object message);
|
||||
|
||||
protected abstract void dispatch(final Object message, final Object listener);
|
||||
|
||||
|
||||
protected IMessageBus getMessageBus(){
|
||||
return owningBus;
|
||||
}
|
||||
|
||||
public int getPriority(){
|
||||
return priority;
|
||||
}
|
||||
|
||||
|
||||
public void subscribe(Object o) {
|
||||
listeners.add(o);
|
||||
|
||||
}
|
||||
|
||||
protected void handlePublicationError(PublicationError error){
|
||||
Collection<IPublicationErrorHandler> handlers = owningBus.getRegisteredErrorHandlers();
|
||||
for(IPublicationErrorHandler handler : handlers){
|
||||
handler.handleError(error);
|
||||
}
|
||||
}
|
||||
|
||||
protected void invokeHandler(final Object message, final Object listener){
|
||||
try {
|
||||
handler.invoke(listener, message);
|
||||
}catch(IllegalAccessException e){
|
||||
handlePublicationError(
|
||||
new PublicationError(e, "Error during messageHandler notification. " +
|
||||
"The class or method is not accessible",
|
||||
handler, listener, message));
|
||||
}
|
||||
catch(IllegalArgumentException e){
|
||||
handlePublicationError(
|
||||
new PublicationError(e, "Error during messageHandler notification. " +
|
||||
"Wrong arguments passed to method. Was: " + message.getClass()
|
||||
+ "Expected: " + handler.getParameterTypes()[0],
|
||||
handler, listener, message));
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
handlePublicationError(
|
||||
new PublicationError(e, "Error during messageHandler notification. " +
|
||||
"Message handler threw exception",
|
||||
handler, listener, message));
|
||||
}
|
||||
catch (Throwable e) {
|
||||
handlePublicationError(
|
||||
new PublicationError(e, "Error during messageHandler notification. " +
|
||||
"Unexpected exception",
|
||||
handler, listener, message));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void unsubscribe(Object existingListener) {
|
||||
listeners.remove(existingListener);
|
||||
}
|
||||
|
||||
|
||||
public static final Comparator<Subscription> SubscriptionByPriorityDesc = new Comparator<Subscription>() {
|
||||
@Override
|
||||
public int compare(Subscription o1, Subscription o2) {
|
||||
int result = o1.getPriority() - o2.getPriority();
|
||||
return result == 0 ? o1.handler.hashCode() - o2.handler.hashCode() : result;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package org.mbassy.subscription;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* User: benni
|
||||
* Date: 11/16/12
|
||||
*/
|
||||
public class SubscriptionDeliveryRequest<T> {
|
||||
|
||||
private Collection<Subscription> subscriptions;
|
||||
|
||||
private T message;
|
||||
|
||||
public SubscriptionDeliveryRequest(Collection<Subscription> subscriptions, T message) {
|
||||
this.subscriptions = subscriptions;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public SubscriptionDeliveryRequest(T message){
|
||||
this.message = message;
|
||||
subscriptions = new LinkedList<Subscription>();
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends Subscription> c) {
|
||||
return subscriptions.addAll(c);
|
||||
}
|
||||
|
||||
public boolean add(Subscription subscription) {
|
||||
return subscriptions.add(subscription);
|
||||
}
|
||||
|
||||
public void execute(){
|
||||
for(Subscription sub : subscriptions)
|
||||
sub.publish(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package org.mbassy.subscription;
|
||||
|
||||
import org.mbassy.IMessageBus;
|
||||
import org.mbassy.IPublicationErrorHandler;
|
||||
import org.mbassy.listener.MessageHandlerMetadata;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: benni
|
||||
* Date: 11/16/12
|
||||
* Time: 10:39 AM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public class SubscriptionFactory {
|
||||
|
||||
private IMessageBus owner;
|
||||
|
||||
|
||||
public SubscriptionFactory(IMessageBus owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Subscription createSubscription(MessageHandlerMetadata messageHandlerMetadata){
|
||||
if(messageHandlerMetadata.isFiltered()){
|
||||
if(messageHandlerMetadata.isAsynchronous()){
|
||||
return new UnfilteredAsynchronousSubscription(owner, messageHandlerMetadata);
|
||||
}
|
||||
else{
|
||||
return new UnfilteredSynchronousSubscription(owner, messageHandlerMetadata);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(messageHandlerMetadata.isAsynchronous()){
|
||||
return new FilteredAsynchronousSubscription(owner, messageHandlerMetadata);
|
||||
}
|
||||
else{
|
||||
return new FilteredSynchronousSubscription(owner, messageHandlerMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package org.mbassy.subscription;
|
||||
|
||||
import org.mbassy.IMessageBus;
|
||||
import org.mbassy.IPublicationErrorHandler;
|
||||
import org.mbassy.MBassador;
|
||||
import org.mbassy.listener.MessageHandlerMetadata;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: benni
|
||||
* Date: 11/14/12
|
||||
* Time: 3:48 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public class UnfilteredAsynchronousSubscription extends UnfilteredSubscription {
|
||||
|
||||
public UnfilteredAsynchronousSubscription(IMessageBus mBassador, MessageHandlerMetadata messageHandler) {
|
||||
super(mBassador, messageHandler);
|
||||
}
|
||||
|
||||
protected void dispatch(final Object message, final Object listener){
|
||||
getMessageBus().getExecutor().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
invokeHandler(message, listener);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package org.mbassy.subscription;
|
||||
|
||||
import org.mbassy.IMessageBus;
|
||||
import org.mbassy.IPublicationErrorHandler;
|
||||
import org.mbassy.MBassador;
|
||||
import org.mbassy.listener.MessageHandlerMetadata;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: benni
|
||||
* Date: 11/14/12
|
||||
* Time: 3:45 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public abstract class UnfilteredSubscription extends Subscription{
|
||||
|
||||
|
||||
public UnfilteredSubscription(IMessageBus mBassador, MessageHandlerMetadata messageHandler) {
|
||||
super(mBassador, messageHandler);
|
||||
}
|
||||
|
||||
public void publish(Object message) {
|
||||
|
||||
Iterator<Object> iterator = listeners.iterator();
|
||||
Object listener = null;
|
||||
while ((listener = iterator.next()) != null) {
|
||||
dispatch(message, listener);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package org.mbassy.subscription;
|
||||
|
||||
import org.mbassy.IMessageBus;
|
||||
import org.mbassy.IPublicationErrorHandler;
|
||||
import org.mbassy.MBassador;
|
||||
import org.mbassy.listener.MessageHandlerMetadata;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
* User: benni
|
||||
* Date: 11/14/12
|
||||
* Time: 3:49 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public class UnfilteredSynchronousSubscription extends UnfilteredSubscription{
|
||||
|
||||
public UnfilteredSynchronousSubscription(IMessageBus mBassador, MessageHandlerMetadata messageHandler) {
|
||||
super(mBassador, messageHandler);
|
||||
}
|
||||
|
||||
protected void dispatch(final Object message, final Object listener){
|
||||
invokeHandler(message, listener);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user