net.corda.node.services.messaging

## Class NodeMessagingClient

- SingletonSerializeAsToken
- - ArtemisMessagingComponent
  - - net.corda.node.services.messaging.NodeMessagingClient

- All Implemented Interfaces:
    MessagingService, MessagingServiceInternal, SerializeAsToken

      public class NodeMessagingClient
      extends ArtemisMessagingComponent
      implements MessagingServiceInternal

  This class implements the `interface MessagingService` API using Apache Artemis, the successor to their ActiveMQ product. Artemis is a message queue broker and here we run a client connecting to the specified broker instance `class ArtemisMessagingServer`. It's primarily concerned with peer-to-peer messaging.

  Message handlers are run on the provided `interface AffinityExecutor` synchronously, that is, the Artemis callback threads are blocked until the handler is scheduled and completed. This allows backpressure to propagate from the given executor through into Artemis and from there, back through to senders.

  An implementation of `interface CordaRPCOps` can be provided. If given, clients using the CordaMQClient RPC library can invoke methods on the provided implementation. There is more documentation on this in the docsite and the CordaRPCClient class.

  See Also:
    `interface MessagingService`, `class ArtemisMessagingServer`, `interface AffinityExecutor`, `interface CordaRPCOps`

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `static class` | `NodeMessagingClient.Companion`
    `static class` | `NodeMessagingClient.Handler` A registration to handle messages of different types

    - ### Nested classes/interfaces inherited from class net.corda.node.services.messaging.ArtemisMessagingComponent

      `ArtemisMessagingComponent.ConnectionDirection, ArtemisMessagingComponent.NetworkMapAddress, ArtemisMessagingComponent.NodeAddress, ArtemisMessagingComponent.ServiceAddress`

  - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static NodeMessagingClient.Companion` | `Companion`
    `static java.lang.String` | `SESSION_ID_PROPERTY`
    `static java.lang.String` | `TOPIC_PROPERTY`

    - ### Fields inherited from class net.corda.node.services.messaging.ArtemisMessagingComponent

      `CLIENTS_PREFIX, INTERNAL_PREFIX, NETWORK_MAP_QUEUE, NODE_USER, NOTIFICATIONS_ADDRESS, P2P_QUEUE, PEERS_PREFIX, PEER_USER, RPC_QUEUE_REMOVALS_QUEUE, RPC_REQUESTS_QUEUE, SERVICES_PREFIX, VERIFY_PEER_COMMON_NAME`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `NodeMessagingClient(NodeConfiguration config, com.google.common.net.HostAndPort serverHostPort, CompositeKey myIdentity, AffinityExecutor nodeExecutor, org.jetbrains.exposed.sql.Database database, com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> networkMapRegistrationFuture)` This class implements the `interface MessagingService` API using Apache Artemis, the successor to their ActiveMQ product. Artemis is a message queue broker and here we run a client connecting to the specified broker instance `class ArtemisMessagingServer`. It's primarily concerned with peer-to-peer messaging.

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `MessageHandlerRegistration` | `addMessageHandler(java.lang.String topic, long sessionID, kotlin.jvm.functions.Function2<? super net.corda.core.messaging.ReceivedMessage,? super net.corda.core.messaging.MessageHandlerRegistration,kotlin.Unit> callback)` The provided function will be invoked for each received message whose topic matches the given string. The callback will run on threads provided by the messaging service, and the callback is expected to be thread safe as a result.
    `MessageHandlerRegistration` | `addMessageHandler(TopicSession topicSession, kotlin.jvm.functions.Function2<? super net.corda.core.messaging.ReceivedMessage,? super net.corda.core.messaging.MessageHandlerRegistration,kotlin.Unit> callback)` The provided function will be invoked for each received message whose topic and session matches. The callback will run on the main server thread provided when the messaging service is constructed, and a database transaction is set up for you automatically.
    `Message` | `createMessage(TopicSession topicSession, byte[] data, java.util.UUID uuid)` Returns an initialised `interface Message` with the current time, etc, already filled in.
    `MessageRecipients` | `getAddressOfParty(PartyInfo partyInfo)` Given information about either a specific node or a service returns its corresponding address
    `NodeConfiguration` | `getConfig()` The config object is used to pass in the passwords for the certificate KeyStore and TrustStore
    `org.jetbrains.exposed.sql.Database` | `getDatabase()`
    `SingleMessageRecipient` | `getMyAddress()` Apart from the NetworkMapService this is the only other address accessible to the node outside of lookups against the NetworkMapCache.
    `CompositeKey` | `getMyIdentity()`
    `com.google.common.util.concurrent.ListenableFuture<kotlin.Unit>` | `getNetworkMapRegistrationFuture()`
    `AffinityExecutor` | `getNodeExecutor()`
    `com.google.common.net.HostAndPort` | `getServerHostPort()`
    `void` | `removeMessageHandler(MessageHandlerRegistration registration)` Removes a handler given the object returned from addMessageHandler. The callback will no longer be invoked once this method has returned, although executions that are currently in flight will not be interrupted.
    `void` | `run()` Starts the p2p event loop: this method only returns once `NodeMessagingClient.stop` has been called.
    `void` | `send(Message message, MessageRecipients target)` Sends a message to the given receiver. The details of how receivers are identified is up to the messaging implementation: the type system provides an opaque high level view, with more fine grained control being available via type casting. Once this function returns the message is queued for delivery but not necessarily delivered: if the recipients are offline then the message could be queued hours or days later.
    `void` | `start(RPCOps rpcOps, RPCUserService userService)`
    `void` | `stop()` Initiates shutdown: if called from a thread that isn't controlled by the executor passed to the constructor then this will block until all in-flight messages have finished being handled and acknowledged. If called from a thread that's a part of the `interface AffinityExecutor` given to the constructor, it returns immediately and shutdown is asynchronous.

    - ### Methods inherited from class net.corda.node.services.messaging.ArtemisMessagingComponent

      `checkStorePasswords, expectedOnDefaultFileSystem, getConfig, tcpTransport, toHostAndPort`

    - ### Methods inherited from class net.corda.core.serialization.SingletonSerializeAsToken

      `toToken`

    - ### Methods inherited from interface net.corda.node.services.api.MessagingServiceInternal

      `stop`

    - ### Methods inherited from interface net.corda.core.messaging.MessagingService

      `addMessageHandler, addMessageHandler, createMessage, getAddressOfParty, getMyAddress, removeMessageHandler, send`

    - ### Methods inherited from interface net.corda.core.serialization.SerializeAsToken

      `toToken`

- - ### Field Detail

    - #### TOPIC_PROPERTY

          public static java.lang.String TOPIC_PROPERTY

    - #### SESSION_ID_PROPERTY

          public static java.lang.String SESSION_ID_PROPERTY

    - #### Companion

          public static NodeMessagingClient.Companion Companion

  - ### Constructor Detail

    - #### NodeMessagingClient

          public NodeMessagingClient(NodeConfiguration config,
                                     com.google.common.net.HostAndPort serverHostPort,
                                     CompositeKey myIdentity,
                                     AffinityExecutor nodeExecutor,
                                     org.jetbrains.exposed.sql.Database database,
                                     com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> networkMapRegistrationFuture)

      This class implements the `interface MessagingService` API using Apache Artemis, the successor to their ActiveMQ product. Artemis is a message queue broker and here we run a client connecting to the specified broker instance `class ArtemisMessagingServer`. It's primarily concerned with peer-to-peer messaging.

      Message handlers are run on the provided `interface AffinityExecutor` synchronously, that is, the Artemis callback threads are blocked until the handler is scheduled and completed. This allows backpressure to propagate from the given executor through into Artemis and from there, back through to senders.

      An implementation of `interface CordaRPCOps` can be provided. If given, clients using the CordaMQClient RPC library can invoke methods on the provided implementation. There is more documentation on this in the docsite and the CordaRPCClient class.

      Parameters:
        `config` - The config object is used to pass in the passwords for the certificate KeyStore and TrustStore
        `serverHostPort` - The address of the broker instance to connect to (might be running in the same process)
        `myIdentity` - Either the public key to be used as the ArtemisMQ address and queue name for the node globally, or null to indicate that this is a NetworkMapService node which will be bound globally to the name "networkmap"
        `nodeExecutor` - An executor to run received message tasks upon.
      See Also:
        `interface MessagingService`, `class ArtemisMessagingServer`, `interface AffinityExecutor`, `interface CordaRPCOps`

  - ### Method Detail

    - #### getMyAddress

          public SingleMessageRecipient getMyAddress()

      Apart from the NetworkMapService this is the only other address accessible to the node outside of lookups against the NetworkMapCache.

    - #### start

          public void start(RPCOps rpcOps,
                            RPCUserService userService)

    - #### run

          public void run()

      Starts the p2p event loop: this method only returns once `NodeMessagingClient.stop` has been called.

      This actually runs as two sequential loops. The first subscribes for and receives only network map messages until we get our network map fetch response. At that point the filtering consumer is closed and we proceed to the second loop and consume all messages via a new consumer without a filter applied.

      See Also:
        `NodeMessagingClient.stop`

    - #### stop

          public void stop()

      Initiates shutdown: if called from a thread that isn't controlled by the executor passed to the constructor then this will block until all in-flight messages have finished being handled and acknowledged. If called from a thread that's a part of the `interface AffinityExecutor` given to the constructor, it returns immediately and shutdown is asynchronous.

      See Also:
        `interface AffinityExecutor`

    - #### send

          public void send(Message message,
                           MessageRecipients target)

      Sends a message to the given receiver. The details of how receivers are identified is up to the messaging implementation: the type system provides an opaque high level view, with more fine grained control being available via type casting. Once this function returns the message is queued for delivery but not necessarily delivered: if the recipients are offline then the message could be queued hours or days later.

      There is no way to know if a message has been received. If your flow requires this, you need the recipient to send an ACK message back.

    - #### addMessageHandler

          public MessageHandlerRegistration addMessageHandler(java.lang.String topic,
                                                              long sessionID,
                                                              kotlin.jvm.functions.Function2<? super net.corda.core.messaging.ReceivedMessage,? super net.corda.core.messaging.MessageHandlerRegistration,kotlin.Unit> callback)

      The provided function will be invoked for each received message whose topic matches the given string. The callback will run on threads provided by the messaging service, and the callback is expected to be thread safe as a result.

      The returned object is an opaque handle that may be used to un-register handlers later with `NodeMessagingClient.removeMessageHandler`. The handle is passed to the callback as well, to avoid race conditions whereby the callback wants to unregister itself and yet addMessageHandler hasn't returned the handle yet.

      Parameters:
        `topic` - identifier for the general subject of the message, for example "platform.network_map.fetch". The topic can be the empty string to match all messages (session ID must be DEFAULT_SESSION_ID).
        `sessionID` - identifier for the session the message is part of. For services listening before a session is established, use DEFAULT_SESSION_ID.
      See Also:
        `NodeMessagingClient.removeMessageHandler`

    - #### addMessageHandler

          public MessageHandlerRegistration addMessageHandler(TopicSession topicSession,
                                                              kotlin.jvm.functions.Function2<? super net.corda.core.messaging.ReceivedMessage,? super net.corda.core.messaging.MessageHandlerRegistration,kotlin.Unit> callback)

      The provided function will be invoked for each received message whose topic and session matches. The callback will run on the main server thread provided when the messaging service is constructed, and a database transaction is set up for you automatically.

      The returned object is an opaque handle that may be used to un-register handlers later with `NodeMessagingClient.removeMessageHandler`. The handle is passed to the callback as well, to avoid race conditions whereby the callback wants to unregister itself and yet addMessageHandler hasn't returned the handle yet.

      Parameters:
        `topicSession` - identifier for the topic and session to listen for messages arriving on.
      See Also:
        `NodeMessagingClient.removeMessageHandler`

    - #### removeMessageHandler

          public void removeMessageHandler(MessageHandlerRegistration registration)

      Removes a handler given the object returned from addMessageHandler. The callback will no longer be invoked once this method has returned, although executions that are currently in flight will not be interrupted.

      Throws:
        - if the given registration isn't valid for this messaging service.
        - if the given registration was already de-registered.

    - #### createMessage

          public Message createMessage(TopicSession topicSession,
                                       byte[] data,
                                       java.util.UUID uuid)

      Returns an initialised `interface Message` with the current time, etc, already filled in.

      Parameters:
        `topicSession` - identifier for the topic and session the message is sent to.
      See Also:
        `interface Message`

    - #### getAddressOfParty

          public MessageRecipients getAddressOfParty(PartyInfo partyInfo)

      Given information about either a specific node or a service returns its corresponding address

    - #### getConfig

          public NodeConfiguration getConfig()

      The config object is used to pass in the passwords for the certificate KeyStore and TrustStore

    - #### getServerHostPort

          public com.google.common.net.HostAndPort getServerHostPort()

    - #### getMyIdentity

          public CompositeKey getMyIdentity()

    - #### getNodeExecutor

          public AffinityExecutor getNodeExecutor()

    - #### getDatabase

          public org.jetbrains.exposed.sql.Database getDatabase()

    - #### getNetworkMapRegistrationFuture

          public com.google.common.util.concurrent.ListenableFuture<kotlin.Unit> getNetworkMapRegistrationFuture()