Class DefaultMessage

java.lang.Object
net.sodacan.core.message.DefaultMessage
All Implemented Interfaces:
Message

public class DefaultMessage extends Object implements Message

All Messages have a messageId and a routing stack. Many have a payload. A message can retain a history of where its been. The top of the route stack is popped just before a message is processed by an actor. A message is enforced to be immutable once it has been sent. A New message can be created from an immutable message, including the same messageId. Additionally, multiple messages can be created from a single immutable message typically for a fan-out fan-in flow.

Implementation note: The only interesting part of the route stack is the top of stack. And, since messages are serialized and sent frequently, we need to serialize and store/transmit the route stack as efficiently as possible. Therefore, don't bother serializing or deserializing most of the route stack for each message invocation. When creating a message, serialize all but the top of stack to a string and and prepend it to the existing serialized string. When processing a message popRoute, pop the (only) route from the top of stack and then peel off the first route in the string and add it to the real stack. In this way, the materialized stack is just a scalar route plus the string carrying the rest of the stack.

  • Constructor Details

    • DefaultMessage

      public DefaultMessage()
    • DefaultMessage

      public DefaultMessage(MessageId messageId)
    • DefaultMessage

      public DefaultMessage(Message source)
  • Method Details

    • from

      public Message from(Message source)
      Copy guts of provided message into this message but don't copy routes. If keepHistory is false but there is lingering history from the original message, the history is NOT brought forward. The messageId is brought forward. Payload is brought forward. This method is used to broadcast messages, with the same id, to multiple actors in parallel. The single messageId allows for correlation of messages when needed.
      Specified by:
      from in interface Message
    • validateMessage

      public boolean validateMessage(Config config)
      If nothing to do in the message, return false. Otherwise, check and throw exception if issues.
      Parameters:
      config -
      Returns:
      true if the message is valid
    • getMessageId

      public MessageId getMessageId()
      Specified by:
      getMessageId in interface Message
    • getTimestamp

      public Instant getTimestamp()
      Specified by:
      getTimestamp in interface Message
    • getHistory

      public List<Route> getHistory()
      Description copied from interface: Message
      Return a copy of the message routing history
      Specified by:
      getHistory in interface Message
      Returns:
    • getRoute

      public Route getRoute()
      Get the current route
      Specified by:
      getRoute in interface Message
      Returns:
      The current route
    • getTarget

      public ActorId getTarget()
      Description copied from interface: Message
      Get the target actorId of the current route. This is the route that gave rise to this call to processMessage
      Specified by:
      getTarget in interface Message
      Returns:
      The current target actorId
    • getVerb

      public Verb getVerb()
      Description copied from interface: Message
      Get the verb of the current route. This is the route that gave rise to this call to processMessage
      Specified by:
      getVerb in interface Message
      Returns:
      The current verb
    • getRoutes

      public List<Route> getRoutes()
      Specified by:
      getRoutes in interface Message
    • getNextActorId

      public ActorId getNextActorId()
      Specified by:
      getNextActorId in interface Message
    • getNextVerb

      public Verb getNextVerb()
      Peek at the next verb or null if there's no more routes.
      Specified by:
      getNextVerb in interface Message
    • peekRoute

      public Route peekRoute()
      Peek at the next route or null if there's no more routes in the message.
      Specified by:
      peekRoute in interface Message
    • peekTailRoute

      public Route peekTailRoute()
    • popRoute

      public Route popRoute()
      Popping a route sets the current route in the message and it also renders the message immutable.
      Specified by:
      popRoute in interface Message
    • pushRoute

      public void pushRoute(Route route)
    • keepHistory

      public Message keepHistory(boolean keepHistory)
      Specified by:
      keepHistory in interface Message
    • isKeepHistory

      public boolean isKeepHistory()
      Specified by:
      isKeepHistory in interface Message
    • trace

      public Message trace(boolean trace)
    • copyRoutesFrom

      public Message copyRoutesFrom(Message inbound)
      Specified by:
      copyRoutesFrom in interface Message
    • prepareBuildRoute

      protected Route prepareBuildRoute()
    • ask

      public Message ask(ActorId actorId)
      Specified by:
      ask in interface Message
    • ask

      public Message ask(String key)
      Specified by:
      ask in interface Message
    • to

      public Message to(Verb verb)
      Specified by:
      to in interface Message
    • toJson

      public void toJson(PrintStream out)
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • print

      public void print(PrintStream out)
      Specified by:
      print in interface Message
    • getPayload

      public Map<String,Object> getPayload()
      Get a fresh copy of the payload of this message
      Specified by:
      getPayload in interface Message
      Returns:
    • remove

      public Message remove(String key)
      Description copied from interface: Message
      Remove entry from payload
      Specified by:
      remove in interface Message
      Parameters:
      key - The key to remove
      Returns:
      the message object
    • put

      public Message put(String key, Object value)
      Add an Info entry to payload, see convenience methods as well.
      Specified by:
      put in interface Message
      Parameters:
      value - The Payload value
      Returns:
      Message builder-style
    • put

      public Message put(String key, String value)
      Put new String entry in payload. Convenience for a String
      Specified by:
      put in interface Message
      Parameters:
      key - A string identifying the payload entry
      value - The Payload value
      Returns:
      Message builder-style
    • put

      public Message put(String key, Integer value)
      Put new Integer entry in payload. Convenience for an Integer
      Specified by:
      put in interface Message
      Parameters:
      key - A string identifying the payload entry
      value - The Payload value
      Returns:
      Message builder-style
    • put

      public Message put(String key, ActorId value)
      Put new entry in payload convenience for an ActorId
      Specified by:
      put in interface Message
      Parameters:
      key - A string identifying the payload entry
      value - The ActorId to add
      Returns:
      Message builder-style
    • get

      public Object get(String key)
      Description copied from interface: Message
      Find the info with the matching name (case insensitive).
      Specified by:
      get in interface Message
      Parameters:
      key -
      Returns:
    • get

      public <T> T get(String key, Class<T> clazz)
      Specified by:
      get in interface Message
    • getString

      public String getString(String key)
      Find the Info record the matching name (case insensitive) and return its String Contents
      Specified by:
      getString in interface Message
      Parameters:
      key -
      Returns:
    • getInteger

      public int getInteger(String key)
      Description copied from interface: Message
      Find the integer Info matching the name (case insensitive) and return its Integer Contents
      Specified by:
      getInteger in interface Message
      Parameters:
      key -
      Returns:
    • getActorId

      public ActorId getActorId(String key)
      Find the Info record the matching name (case insensitive) and return its String Contents
      Specified by:
      getActorId in interface Message
      Parameters:
      key -
      Returns:
    • preprocess

      public boolean preprocess(Config config, Actor actor)
      Description copied from interface: Message
      This method is called after a message is deserialized and ready to be processed by the target actor. The default implementation does nothing. This method can be overridden in a Message subclass to provide fine-grained tracing or additional message validation.

      This method executes in the Actor's thread.

      Specified by:
      preprocess in interface Message
      Parameters:
      config -
      actor - The Actor that is about to process this message
      Returns:
      true if the message should be processed
    • postprocess

      public boolean postprocess(Config config, Actor actor)
      Description copied from interface: Message
      This method is called when a message is sent by an Actor. This happens just before the message is serialized for transport to its current destination. A subclass of a default message can use this method to evaluate the message as well as the Actor that created or forwarded the message. This method can be overridden in a Message subclass to provide fine-grained tracing.

      This method executes in the Actor's thread.

      Specified by:
      postprocess in interface Message
      Parameters:
      config -
      actor - The Actor that just processed this message
      Returns:
      true if the message should be processed
    • notImplemented

      public Stage notImplemented(Config config, Actor actor)
      Description copied from interface: Message
      This method is called when a message is sent to an Actor but the Actor has not overriden the processMessage method. The default behavior is to return an empty Stage. An alternate would be to put the inbound message back into the Stage (it will be sent to the next item in the Route stack, if any). A subclass of a default message can use this method to provide alternate behavior or to forwarded the message.

      This method executes in the Actor's thread.

      Specified by:
      notImplemented in interface Message
      Parameters:
      config -
      actor - The Actor that received (but didn't process) this message
      Returns:
      The Stage to be processed
    • terminal

      public void terminal(Config config, Actor actor)
      Description copied from interface: Message
      This method is called when a message is sent by an Actor and the message as no further routes this it will be destroyed just after this method is called. A subclass of a default message can use this method to evaluate the message as well as the Actor that created or forwarded the message to ensure that its demise is justified.

      This method executes in the Actor's thread.

      Specified by:
      terminal in interface Message
      Parameters:
      config -
      actor - The Actor that just processed this message