package ca.szc.keratin.core.net.mbassador; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import net.engio.mbassy.bus.MessagePublication; import net.engio.mbassy.common.IConcurrentSet; import net.engio.mbassy.dispatch.IHandlerInvocation; import net.engio.mbassy.dispatch.MessageDispatcher; import net.engio.mbassy.subscription.SubscriptionContext; import org.pmw.tinylog.Logger; public class TimeoutMessageDispatcher extends MessageDispatcher { private static final ExecutorService service = Executors.newCachedThreadPool(); // Super doesn't specify types, can't do anything to correct that @SuppressWarnings( "rawtypes" ) public TimeoutMessageDispatcher( SubscriptionContext context, IHandlerInvocation invocation ) { super( context, invocation ); } // Super doesn't specify types, can't do anything to correct that @SuppressWarnings( { "unchecked", "rawtypes" } ) @Override public void dispatch( MessagePublication publication, final Object message, IConcurrentSet listeners ) { publication.markDelivered(); for ( final Object listener : listeners ) { Future future = service.submit( new Runnable() { @Override public void run() { getInvocation().invoke( listener, message ); } } ); try { future.get( 10, TimeUnit.SECONDS ); } catch ( InterruptedException e ) { Thread.currentThread().interrupt(); } catch ( ExecutionException e ) { Logger.error( e, "Handler threw exception on invocation" ); } catch ( TimeoutException e ) { future.cancel( true ); Logger.error( "Invocation timed out for handler in listener " + listener + " with message " + message ); } } } }