Class EHistoricPublishFeed
- java.lang.Object
-
- net.sf.eBus.feed.historic.EAbstractHistoricFeed<IEHistoricPublisher>
-
- net.sf.eBus.feed.historic.EHistoricPublishFeed
-
- All Implemented Interfaces:
EObject,EPublisher,EReplier
public final class EHistoricPublishFeed extends EAbstractHistoricFeed<IEHistoricPublisher> implements EPublisher, EReplier
The historic publisher feed extendsEPublishFeed's ability to publish notification messages to subscribers with the ability to:-
persist notification messages to a
IEMessageStoreimplementation and -
handle
historic notification requestsretrieving previously published messages from message store.
Please note that
ESubscribers are able to seamlessly access notification messages posted to an historic publish feed. There is no distinction between live-only and historic feeds. Of course anESubscribercannot access previously published notification messages.Note: an
IEMessageStoreinstance may be shared between multipleEHistoricPublishFeeds but the implementation is responsible for maintaining thread safety.EHistoricPublishFeedis similar to using anEPublishFeed:Step 1: Implement
IEHistoricPublisherinterface.Step 2: Open an historic publish feed using an
EHistoricPublishFeed.Builderinstance (obtained usingbuilder(EMessageKey, IEHistoricPublisher)) for a givenIEHistoricPublisherinstance,type+topic message key,feed scope, andIEMessageStoreinstance.Note: historic notification feeds are dependent on setting a unique publisher identifier. This allows historic feed subscribers to differentiate between publishers.
Note that when opening an historic publish feed, the configured message store must be open and ready to persist and retrieve historic notification messages.
Step 3:
Start uphistoric publish feed. Call this method directly rather than usingEFeed.register(net.sf.eBus.client.EObject)andEFeed.startup(net.sf.eBus.client.EObject)becauseEHistoricPublishFeedis an eBus hybrid object and runs in theIEHistoricPublisher's dispatcher. The underlying historic notification reply feed is opened, advertised, and feed state set to up at this time. This means the historic publish feed is able to process historic notification requests even when the publish feed is unadvertised.Step 4:
Advertisethis publisher to eBus. This allows eBus to match publishers with subscribers.Step 5:
Set feed statetoup. This step must be done prior to publishing any notifications. Put another way, notifications cannot be published when the feed state is not up.Step 6:
Start publishingnotifications. Note that this differs fromEPublishFeedwhere the publisher must wait for subscribers prior to posting a notification. This is because notifications need to be persisted despite the lack of subscribers. This allows anIEHistoricSubscriberto access previously published messages when opening itshistoric subscribe feed.It is highly recommended that publishers set
ENotificationMessage.positionvalues especially if more than one notification is published per millisecond.Step 7: When shutting down the publisher
retractnotification advertisement andclosethe historic feed.Example use of
EHistoricPublishFeedimport net.sf.eBus.client.EFeed.FeedScope; import net.sf.eBus.client.EFeedState; import net.sf.eBus.feed.historic.IEHistoricPublisher; import net.sf.eBus.feed.historic.EHistoriicPublishFeed; import net.sf.eBus.messages.EMessageKey; import net.sf.eBus.messages.ENotificationMessage; // Step 1: Implement IEHistoricPublisher interface. public class CatalogPublisher implements IEHistoricPublisher { // Roll over notification position when this value is reached. private static final int MAX_POSITION = 1_000; // HistoricReply messages contain up to 10 notifications per reply message. private static final int MAX_NOTIFICATIONS_PER_REPLY = 10; // Publishes this notification message class/subject key. private final EMessageKey mKey; // Unique publisher identifier. private final long mPublisherId; // Catalog publisher name used for logging purposes. private final String mName; // Published messages remain within this scope. private final FeedScope mScope; // Message store for persisting and retrieving notification messages. private final IEMessageStore mStore; // Advertise and publish on this feed. private EHistoricPublishFeed mFeed; // Latest message position. Incremented on each notification publish. // Value is reset to zero when MAX_POSITION is reached. private int mPosition; public CatalogPublisher(final String subject, final long pubId, final FeedScope scope, final IEMessageStore store) { mKey = new EMessageKey(CatalogUpdate.class, subject); mPublisherId = pubId; mName = (this.getClass()).getSimpleName + "-" + pubId; mScope = scope; mStore = store; mFeed = null; mPosition = 0; } @Override public void startup() { try { // Step 2: Open publish feed. Place IEHistoricPublisher interface method overrides here. // This publisher overrides IEHistoricPublisher interface method. final EHistoricPublishFeed.Builder builder = EHistoricPublishFeed.builder(this, mKey); mFeed = builder.name(mName) .scope(mScope) .messageStore(mStore) .notificationsPerReply(MAX_NOTIFICATIONS_PER_REPLY) .build(); // Step 3: Start up this publisher. mFeed.startup(); // Step 4: Advertise this publisher to eBus. mFeed.advertise(); // Step 5: Inform the world that this publisher's feed state is up. mFeed.updateFeedState(EFeedState.UP); } catch (IllegalArgumentException argex) { // Advertisement failed. Place recovery code here. } } // Note: this method is never called by EHistoricPublishFeed since the publishStatus is always up once // historic publish feed is opened, advertised, and publish feed state is set to up. @Override public void publishStatus(final EFeedState feedState, final EPublishFeed feed) { ... } // Step 6: Start publishing notifications. public void updateProduct(final String productName, final Money price, final int stockQty) { if (mFeed != null && mFeed.inPlace()) { mFeed.publish((CatalogUpdate.builder()).subject(mKey.subject) .timestamp(Instant.now()) .publisherId(mPublisherId) .position(mPosition) .productName(productName) .price(price) .inStockQuantity(stockQty) .build()); ++mPosition; // Reset position? if (mPosition == MAX_POSITION) { mPosition = 0; } } } // Retract the notification feed. @Override public void shutdown() { Step 7: On shutdown either unadvertise or close publish feed. if (mFeed != null) { // unadvertise() unnecessary since close() retracts an in-place advertisement. mFeed.close(); mFeed = null; } } }Historic Publisher and Message Exhaust
eBus release 6.2.0 introducedmessage exhaust interfacewhich allows all messages (notification, request, reply) flowing through eBus to be exhausted to persistent store. The difference between this and an historic publisher is that the historic publisher persists a notification message even if it is not published to eBus which message exhaust persists only those messages successfully published to eBus. The reason for historic feeds is to allow subscribers to retrieve historic and live notification messages in a seamless manner. The reason for message exhaust is to track what messages flowed through eBus. This allows the user to recreate what happened when a system error occurred.- Author:
- Charles W. Rapp
- See Also:
EPublishFeed,IEHistoricPublisher,EHistoricSubscribeFeed,IEHistoricSubscriber
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static classEHistoricPublishFeed.BuilderBuilder is used to instantiateEHistoricPublishFeedinstances.
-
Field Summary
Fields Modifier and Type Field Description static intDEFAULT_NOTIFICATIONS_PER_REPLYDefault maximum number of notifications perHistoricReplyis 5.static StringDEFAULT_PUBLISH_FEED_NAMEIf historic publish feed name is not set, then defaults to "EHistoricPublishFeed-" appended with feed index.-
Fields inherited from class net.sf.eBus.feed.historic.EAbstractHistoricFeed
mFeedState, mInPlace, mIsOpen, mKey, mName, mOwner, mRequestKey, mScope, mStatusKey
-
Fields inherited from interface net.sf.eBus.client.EObject
NAME_NOT_SET
-
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description voidadvertise()Advertises publisher feed and historic reply feed associated with message key.static EHistoricPublishFeed.Builderbuilder(EMessageKey key, IEHistoricPublisher publisher)Returns a new historic publish feed builder for the specified notification message key and publisher identifier.protected voiddoClose()Closes subordinate notification and request feeds, if open.booleanisFeedUp()Returnstrueif this historic publish feed is 1) open, 2) advertised, and 3) feed state is up; otherwise returnstrueStringname()Returns historic publish feed's eBus object name.intnotificationsPerReply()Returns maximum number of historic notifications placed in a historic message reply.voidpublish(ENotificationMessage msg)First persists this notification to message store and then, if the notification feed is up.longpublisherId()Returns historic publisher identifier.voidshutdown()Closes all extand publish and reply feeds.voidstartup()Opens notification andPublishStatusEventpublish feeds, and historic request reply feeds but leaves them un-advertised.voidunadvertise()Retracts both the notification publish and historic reply feeds.voidupdateFeedState(EFeedState update)Updates publish feed state to the given value.-
Methods inherited from class net.sf.eBus.feed.historic.EAbstractHistoricFeed
close, closeFeed, feedState, inPlace, isOpen, key, publisherStatusKey, requestKey, scope
-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface net.sf.eBus.client.EPublisher
publishStatus
-
Methods inherited from interface net.sf.eBus.client.EReplier
cancelRequest, request
-
-
-
-
Field Detail
-
DEFAULT_NOTIFICATIONS_PER_REPLY
public static final int DEFAULT_NOTIFICATIONS_PER_REPLY
Default maximum number of notifications perHistoricReplyis 5.- See Also:
- Constant Field Values
-
DEFAULT_PUBLISH_FEED_NAME
public static final String DEFAULT_PUBLISH_FEED_NAME
If historic publish feed name is not set, then defaults to "EHistoricPublishFeed-" appended with feed index.- See Also:
- Constant Field Values
-
-
Method Detail
-
doClose
protected void doClose()
Closes subordinate notification and request feeds, if open.- Specified by:
doClosein classEAbstractHistoricFeed<IEHistoricPublisher>
-
name
public String name()
Returns historic publish feed's eBus object name. Used for logging purposes only.
-
startup
public void startup()
Opens notification andPublishStatusEventpublish feeds, and historic request reply feeds but leaves them un-advertised. These feeds are advertised whenadvertise()is called.- Specified by:
startupin interfaceEObject- See Also:
advertise(),unadvertise()
-
shutdown
public void shutdown()
Closes all extand publish and reply feeds.
-
publisherId
public long publisherId()
Returns historic publisher identifier.- Returns:
- historic publisher identifier.
-
notificationsPerReply
public int notificationsPerReply()
Returns maximum number of historic notifications placed in a historic message reply.- Returns:
- maximum number of historic messages per reply.
-
isFeedUp
public boolean isFeedUp()
Returnstrueif this historic publish feed is 1) open, 2) advertised, and 3) feed state is up; otherwise returnstrue- Returns:
trueif historic publisher is clear to publish notification messages.
-
advertise
public void advertise()
Advertises publisher feed and historic reply feed associated with message key. If this historic feed is currently advertised, then does nothing. Historic feed publisher may publish notifications only after both advertising the feed and setting the publish status toup. Note: once the publisher has advertised and marked this historic feed as up, the publisher is free to publish notifications even if there are no subscribers to this feed since all notification messages are persisted.- Throws:
IllegalStateException- if this feed is closed.- See Also:
unadvertise(),updateFeedState(EFeedState),shutdown()
-
unadvertise
public void unadvertise()
Retracts both the notification publish and historic reply feeds. Does nothing if this historic feed is not currently advertised.- See Also:
advertise(),shutdown()
-
updateFeedState
public void updateFeedState(EFeedState update)
Updates publish feed state to the given value. Ifupdateequals the current state, nothing is done. Otherwise this new publish feed state is forwarded to the underlyingEPublishFeedand persisted to this historic message store.- Parameters:
update- new publish feed state.- Throws:
NullPointerException- ifupdateisnull.IllegalStateException- if this feed is not advertised.
-
publish
public void publish(ENotificationMessage msg)
First persists this notification to message store and then, if the notification feed is up. Historic publish feeds differ fromEPublishFeedin that notifications may be published even when the feed is down.If any exception is thrown, this means the message was not persisted.
- Parameters:
msg- post this notification message to subscribers.- Throws:
NullPointerException- ifmsgisnull.IllegalArgumentException- ifmsgmessage key or publisher identifier does not match the feed's values.IllegalStateException- if this feed is not advertised or the publisher has not declared the feed to be up.
-
builder
public static EHistoricPublishFeed.Builder builder(EMessageKey key, IEHistoricPublisher publisher)
Returns a new historic publish feed builder for the specified notification message key and publisher identifier. It is recommended that a new builder be obtained for each historic publish feed rather than re-using an existing builder.- Parameters:
key- published notification message key.publisher- historic publisher associated with this feed.- Returns:
- new historic publish feed builder.
- Throws:
NullPointerException- ifkeyorpublisherisnull.IllegalArgumentException- ifkeyis not a notification message.
-
-