title: Implementing Content-Based Router Pattern in Akka
body: <p>I am trying to implement a <a href="http://www.enterpriseintegrationpatterns.com/ContentBasedRouter.html" rel="nofollow">content-based router</a> in my Akka actor system and according to <a href="https://gist.github.com/jboner/8556813" rel="nofollow">this document</a> the <a href="http://doc.akka.io/docs/akka/2.1.4/java/routing.html" rel="nofollow">ConsistentHashingRouter</a> is the way to go. After reading through its official docs, I still find myself confused as to how to use this built-in hashing router. I think that’s because the router itself is hash/key-based, and the example the Akka doc author chose to use was a scenario involving key-value based caches…so I can’t tell which keys are used by the cache and which ones are used by the router!</p>
  
  <p>Let’s take a simple example. Say we have the following messages:</p>
  
  <pre><code>interface Notification {
      // Doesn’t matter what’s here.
  }
  
  // Will eventually be emailed to someone.
  class EmailNotification implements Notification {
      // Doesn’t matter what’s here.
  }
  
  // Will eventually be sent to some XMPP client and on to a chatroom somewhere.
  class ChatOpsNotifications implements Notification {
      // Doesn’t matter what’s here.
  }
  </code></pre>
  
  <p>etc. In theory we might have 20 <code>Notification</code> impls. I’d like to be able to send a <code>Notification</code> to an actor/router at runtime and have that router route it to the correct <code>NotificationPubisher</code>:</p>
  
  <pre><code>interface NotificationPublisher&lt;NOTIFICATION implements Notification&gt; {
      void send(NOTIFICATION notification)
  }
  
  class EmailNotificationPublisher extends UntypedActor implements NotificationPubisher&lt;EmailNotification&gt; {
      @Override
      void onReceive(Object message) {
          if(message instanceof EmailNotification) {
              send(message as EmailNotification)
          }
      }
  
      @Override
      void send(EmailNotification notification) {
          // Use Java Mail, etc.
      }
  }
  
  class ChatOpsNotificationPublisher extends UntypedActor implements NotificationPubisher&lt;ChatOpsNotification&gt; {
      @Override
      void onReceive(Object message) {
          if(message instanceof ChatOpsNotification) {
              send(message as ChatOpsNotification)
          }
      }
  
      @Override
      void send(ChatOpsNotification notification) {
          // Use XMPP/Jabber client, etc.
      }
  }
  </code></pre>
  
  <p>Now I <em>could</em> do this routing myself, manually:</p>
  
  <pre><code>class ReinventingTheWheelRouter extends UntypedActor {
      // Inject these via constructor
      ActorRef emailNotificationPublisher
      ActorRef chatOpsNotificationPublisher
      // ...20 more publishers, etc.
  
      @Override
      void onReceive(Object message) {
          ActorRef publisher
          if(message instanceof EmailNotification) {
              publisher = emailNotificationPublisher
          } else if(message instanceof ChatOpsNotification) {
              publisher = chatOpsNotificationPublisher
          } else if(...) { ... } // 20 more publishers, etc.
  
          publisher.tell(message, self)
      }
  }
  </code></pre>
  
  <p>Or I <em>could</em> use the <a href="http://doc.akka.io/docs/akka/snapshot/scala/camel.html" rel="nofollow">Akka-Camel module</a> to defined a Camel-based router and send <code>Notifications</code> off to the Camel router, but it seems that Akka aready has this built-in solution, so why not use it? I just cant figure out how to translate the <code>Cache</code> example from those Akka docs to my <code>Notification</code> example here. What’s the purpose of the “key” in the <code>ConsistentHashingRouter</code>? What would the code look like to make this work?</p>
  
  <p><strong>Of course I would appreciate any answer that helps me solve this, but would greatly prefer Java-based code snippets if at all possible. Scala looks like hieroglyphics to me.</strong></p>
  
  <hr>
  
  <p>I agree that a <a href="http://doc.akka.io/docs/akka/2.3.12/java/routing.html#Custom_Router" rel="nofollow">Custom Router</a> is more appropriate than <code>ConsistentHashingRouter</code>. After reading the docs on custom routers, it seems I would:</p>
  
  <ol>
  <li>Create a <code>GroupBase</code> impl and send messages to it directly (<code>notificationGroup.tell(notification, self)</code>); then</li>
  <li>The <code>GroupBase</code> impl, say, <code>NotificationGroup</code> would provide a <code>Router</code> instance that was injected with my custom <code>RoutingLogic</code> impl</li>
  <li>When <code>NotificationGroup</code> receives a message, it executes my custom <code>RoutingLogic#select</code> method which determines which <code>Routee</code> (I presume some kind of an actor?) to send the message to</li>
  </ol>
  
  <p>If this is correct (and <strong>please correct me if I’m wrong</strong>), then the routing selection magic happens here:</p>
  
  <pre><code>class MessageBasedRoutingLogic implements RoutingLogic {
      @Override
      Routee select(Object message, IndexedSeq&lt;Routee&gt; candidates) {
          // How can I query the Routee interface and deterine whether the message at-hand is in fact
          // appropriate to be routed to the candidate?
          //
          // For instance I'd like to say "If message is an instance of
          // an EmailNotification, send it to EmailNotificationPublisher."
          //
          // How do I do this here?!?
          if(message instanceof EmailNotification) {
              // Need to find the candidate/Routee that is
              // the EmailNotificationPublisher, but how?!?
          }
      }
  }
  </code></pre>
  
  <p>But as you can see I have a few mental implementation hurdles to cross. The <code>Routee</code> interface doesn’t really give me anything I can intelligently use to decide whether a particular <code>Routee</code> (candidate) is correct for the message at hand.</p>
  
  <p>So I ask: (1) How can I map messages to <code>Routees</code> (effectively performing the route selection/logic)? (2) How do I add my publishers as routees in the first place? And (3) Do my <code>NotificationPublisher</code> impls still need to extend <code>UntypedActor</code> or should they now implement <code>Routee</code>?</p>