net.sf.eBus.client.package-info Maven / Gradle / Ivy
//
// Copyright 2012, 2014 - 2016, 2018, 2022 Charles W. Rapp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
/**
* This package contains the top-level eBus API which
* applications use to interact with eBus. This interaction is
* done through {@link net.sf.eBus.client.EFeed} objects. All
* feed objects are associated with a unique type+topic
* {@link net.sf.eBus.messages.EMessageKey message key}.
* Message Key Dictionary
*
* eBus v. 4.5.0 added the ability to directly add messages keys
* to the eBus message key dictionary and retrieve keys from said
* dictionary. Prior to this version, message keys were
* indirectly added to the dictionary when opening feeds. This
* feature added to support the new
* multi-subject feeds.
* Multi-subject feeds may use a
* ¯{@link net.sf.eBus.util.regex.Pattern query} to
* match a variable number of keys. This is why
* {@link net.sf.eBus.client.EFeed#addKey(net.sf.eBus.messages.EMessageKey)},
* {@link net.sf.eBus.client.EFeed#addAllKeys(java.util.Collection)} and
* {@link net.sf.eBus.client.EFeed#loadKeys(java.io.ObjectInputStream)} methods are
* provided: unless the message key dictionary is populated with
* keys prior to creating a multi-subject query feed, the query would
* find no matching keys.
*
* Simple Feeds
*
* A simple feed is associated with a single message key and
* messages are sent to or received from the feed only after the
* feed is opened and advertised/subscribed. Simple feeds provide
* no value added capabilities beyond this.
*
*
* -
* {@link net.sf.eBus.client.EPublishFeed}: Publishers
* advertise and publish
* {@link net.sf.eBus.messages.ENotificationMessage notification messages}
* via a publish feed instance.
*
* -
* {@link net.sf.eBus.client.ESubscribeFeed}:
* Subscribers hook into this feed to receive notification
* messages.
*
* -
* {@link net.sf.eBus.client.EReplyFeed}: Repliers
* advertise their ability to send
* {@link net.sf.eBus.messages.EReplyMessage reply messages}
* in response to a
* {@link net.sf.eBus.messages.ERequestMessage request messages}.
*
* Note that replies are sent back using a
* {@link net.sf.eBus.client.EReplyFeed.ERequest} and not the
* {@code EReplyFeed}.
*
* -
* {@link net.sf.eBus.client.ERequestFeed}: Requestors
* place request messages and receive replies using the
* request feed.
*
*
* Multi-Subject Feeds
* eBus v. 4.5.0 introduced multi-subject feeds, one for each of
* the above four simple feeds. A multi-subject feed is not a
* true {@link net.sf.eBus.client.EFeed} subclass but acts as a
* proxy between an application object and multiple subordinate
* feeds for the same message class. The multi-subject
* feed is responsible for keeping the subordinate feeds in the
* same state (opened, advertised/subscribed,
* un-advertised/un-subscribed, closed), configuring the
* subordinate feeds with the same callbacks.
*
* A multi-subject feed is configured to work with a single
* notification/request message class and multiple message
* subjects. An application object needing a multi-subject feed for
* multiple message classes must open a different multi-subject feed
* for each message class.
*
* The supported multi-subject feeds are:
*
* -
* {@link net.sf.eBus.client.EMultiPublishFeed}:
* uses {@code EPublishFeed} subordinate feeds.
*
* -
* {@link net.sf.eBus.client.EMultiSubscribeFeed}:
* uses {@code ESubscribeFeed} subordinate feeds.
*
* -
* {@link net.sf.eBus.client.EMultiRequestFeed}:
* uses {@code ERequestFeed} subordinate feeds.
*
* -
* {@link net.sf.eBus.client.EMultiReplyFeed}:
* uses {@code EReplyFeed} subordinate feeds.
*
*
* See {@link net.sf.eBus.client.EMultiFeed EMultiFeed} for a
* detailed explanation on how to create and use multi-feeds.
* Roles
* Each of the above feeds has a matching interface which an
* application class must implement if it is to work with that
* feed type:
*
* -
* {@link net.sf.eBus.client.EPublisher}: Required
* interface for
* {@link net.sf.eBus.client.EPublishFeed#publish(net.sf.eBus.messages.ENotificationMessage) publishing}
* notification messages.
*
* -
* {@link net.sf.eBus.client.ESubscriber}: Required
* interface for
* {@link net.sf.eBus.client.ESubscribeFeed#subscribe() subscribing}
* to notification messages.
*
* -
* {@link net.sf.eBus.client.EReplier}: Required
* interface for
* {@link net.sf.eBus.client.EReplyFeed.ERequest#reply(net.sf.eBus.messages.EReplyMessage) replying}
* to requests.
*
* -
* {@link net.sf.eBus.client.ERequestor}: Required
* interface for
* {@link net.sf.eBus.client.ERequestFeed#request(net.sf.eBus.messages.ERequestMessage) posting requests}.
*
*
*
* eBus v. 4.2.0 added support for using Java lambda expressions
* as a callback target. An application still must implement the
* matching role interface for a given feed but is not required
* to override interface methods. Instead, an application uses
* Java lambda expressions to define the callback target. See
* {@link net.sf.eBus.client.FeedStatusCallback},
* {@link net.sf.eBus.client.NotifyCallback},
* {@link net.sf.eBus.client.ReplyCallback}, and
* {@link net.sf.eBus.client.RequestCallback} for more
* information.
*
* Remote Communication
* eBus applications can transmit messages between each other
* using either TCP, UDP, or multicast connections.
* eBus TCP/UDP Connection
* TCP and UDP
* communication is encapsulated in an
* {@link net.sf.eBus.client.ERemoteApp} instance. This instance
* is either created by the application direction to initiate
* a connection to another eBus application or is created by an
* {@link net.sf.eBus.client.EServer} instance upon accepting a
* remotely initiated connection. {@code ERemoteApp} and
* {@code EServer} instances are created configuring an instance
* using the appropriate builder. For {@code ERemoteApp} the
* {@link net.sf.eBus.config.EConfigure.ConnectionBuilder} is used (this
* builder instance is acquired using
* {@link net.sf.eBus.config.EConfigure#connectionBuilder()}).
* {@code EServer} configuration is created using
* {@link net.sf.eBus.config.EConfigure.ServerBuilder} (acquired using
* {@link net.sf.eBus.config.EConfigure#serverBuilder()}).
* Once the configuration is successfully built then open the
* remote application or server instance using
* {@link net.sf.eBus.client.ERemoteApp#openConnection(net.sf.eBus.config.EConfigure.RemoteConnection)}
* or
* {@link net.sf.eBus.client.EServer#openServer(net.sf.eBus.config.EConfigure.Service)},
* respectively.
*
* These instance may be created directly in application code or
* indirectly at application start using the command line option:
*
* -Dnet.sf.eBus.net.config.jsonFile=<conf file path>
*
* This will automatically open the remote client connections and
* servers on start up.
*
*
*
* As of eBus release 6.0.0 Java properties are no longer
* supported with respect to eBus configuration. Only
* typesfafe JSON configuration files may be used.
*
*
*
* Aside: it may appear strange the eBus has a
* {@link net.sf.eBus.client.EUDPServer} since UDP is a
* session-less protocol. But eBus communication is
* session-based. So eBus adds a session layer on top of the UDP
* connection. The UDP connection initiator sends a
* {@link net.sf.eBus.client.sysmessages.UdpConnectRequest UDP connect request}
* message to the {@code EUDPServer}. A
* {@link net.sf.eBus.client.sysmessages.UdpConnectReply UDP connect reply}
* is sent and, if the UDP connection is accepted, the random UDP
* port assigned to the connection which the initiating client
* should use for all further communication.
*
*
* eBus also supports both secure TCP (using SSL/TLS) and secure
* UDP (using DTLS) for remote connections. But this option is
* not supported in configuration file since that would require
* placing sensitive information into the JSON {@code .conf}
* file in the clear.
*
* eBus UDP Multicast Connection
* eBus allows
* {@link net.sf.eBus.messages.ENotificationMessage notification}
* messages to be transmitted between applications. Since
* Multicast is session-less and cannot easily be turned into a
* session-based protocol eBus handles multicasting differently.
*
* There are two types of multicast connections:
* multicast publisher and multicast subscriber. The multicast
* publisher uses an eBus multi-feed subscription to
* receive the desired notification messages. These notifications
* must be locally published with either
* {@link net.sf.eBus.client.EFeed.FeedScope#LOCAL_AND_REMOTE} or
* {@link net.sf.eBus.client.EFeed.FeedScope#REMOTE_ONLY} feed scope.
* The multicast publisher multicasts via
* {@link net.sf.eBus.client.sysmessages.McastKeyMessage} the
* message key (message class and subject), unique integer
* message key identifier, and the message feed state (up or
* down). Locally published notifications are mulicast
* immediately upon receipt. Note that the multicast publisher
* does not track whether there are any remote eBus
* applications joined to the multicast group and subscribed to
* the message key. Local notifications are sent no matter what.
*
*
* Multicast subscriber is the opposite: it takes notifications
* from the multicast group and uses a publisher multi-feed to
* inject the message into eBus. Upon successfully joining the
* configured multicast group the multicast subscriber posts a
* {@link net.sf.eBus.client.sysmessages.McastSubscribeMessage}
* which causes all the joined multicast publishers to transmit
* their current feed status messages. Multicast subscriber
* publish feeds have a
* {@link net.sf.eBus.client.EFeed.FeedScope#REMOTE_ONLY}
* scope.
*
*
* Multicast publishers and subscribers are configured at start
* to support a defined set of message keys. This set cannot be
* altered once the multicast instance is created. That said,
* there is one way to dynamically add new subjects to a
* multicast instance: by have that instance use a
* {@link net.sf.eBus.util.regex.Pattern query}-based multi-feed.
* As new subject feeds come on line the multicast instance will
* either publish or receive the subject feed via the multicast
* group.
*
* Monitoring eBus Connections
* eBus reports the latest connection, server, and multicast
* status using
* using the {@link net.sf.eBus.client.ConnectionMessage},
* {@link net.sf.eBus.client.ServerMessage}, and
* {@link net.sf.eBus.client.MulticastMessage} messages,
* respectively. To track connection status create an
* {@link net.sf.eBus.client.ESubscriber} which subscribes to
* the appropriate message key for the desired connection type.
* Status messages will be sent to the subscribe feed callback
* method. The status message keys for the supported eBus
* connection types are:
*
* -
* TCP, Secure TCP, UDP, Secure UDP connection:
* {@link net.sf.eBus.client.ConnectionMessage#MESSAGE_KEY}
*
* -
* TCP, UDP server:
* {@link net.sf.eBus.client.ServerMessage#MESSAGE_KEY}
*
* -
* UDP multicast:
* {@link net.sf.eBus.client.MulticastMessage#MESSAGE_KEY}
*
*
* Exhausting eBus Messages
* An application may need to persist all messages passing
* through a local eBus. It is not feasible to have a persistence
* mechanism in each application object sending or receiving eBus
* messages. eBus v. 6.2.0 provides a mechanism to exhaust all
* local messages to a persistent store via the
* {@link net.sf.eBus.client.IMessageExhaust} interface.
*
* An application needing to persist all local messages
* accomplishes this by implementing this interface and
* registering an {@code IMessageExhaust} instance with
* {@link net.sf.eBus.client.ESubject#setExhaust(net.sf.eBus.client.IMessageExhaust)}.
* This application exhaust is called via an eBus dispatcher
* thread so as not to interfere with message delivery.
*
*
* Note that only one exhaust may be registered at a
* time. If an application needs to persist a message in
* multiple stores, then that must be done by the single
* application exhaust. If an application does not want to
* exhaust all messages, that filtering must be done by the
* application exhaust. If
* {@link net.sf.eBus.client.IMessageExhaust#exhaust(net.sf.eBus.messages.EMessage)}
* should throw an exception (whether deliberate or not), that
* exception will be caught and logged as a warning.
*
*
* Note: an application using this exhaust
* API is responsible for opening and closing the persistent
* store when appropriate.
*
*
* The default message exhaust does nothing with the message.
*
*/
package net.sf.eBus.client;