Class EReplyFeed
- java.lang.Object
-
- net.sf.eBus.client.EFeed
-
- net.sf.eBus.client.EReplyFeed
-
- All Implemented Interfaces:
IEFeed
,IEReplyFeed
public final class EReplyFeed extends EFeed implements IEReplyFeed
EReplyFeed
is the application entry point for posting replies torequest messages
to requesters. Follow these steps to use this feed:Step 1: Implement
EReplier
interface.Step 2:
Build
reply feed forEReplier
instance andtype+topic request message key
. The condition is optional and may benull
. If provided, then only request messages satisfying the condition are forwarded to the replier.Use
EReplyFeed.Builder.cancelRequestCallback(CancelRequestCallback)
andEReplyFeed.Builder.requestCallback(RequestCallback)
to set Java lambda expressions used in place ofEReplier
interface methods.Step 3:
Advertise
this replier to eBus. This allows eBus to match repliers with requesters.Step 4: Wait for
requests
to arrive. Keep the givenEReplyFeed.ERequest
instance handy becauseERequest
is used to post reply messages back to the requester, notEReplyFeed
.Step 5:
Send
one or morereply
messages back to the requester.Step 6: When the replier is shutting down,
retract
the reply advertisement andclose
the feed.Example use of
EReplyFeed
import java.util.ArrayList; import java.util.List; import net.sf.eBus.client.EFeed.FeedScope; import net.sf.eBus.client.EReplier; import net.sf.eBus.client.EReplyFeed; import net.sf.eBus.messages.EMessageKey; import net.sf.eBus.messages.EReplyMessage; import net.sf.eBus.messages.EReplyMessage.ReplyStatus; import net.sf.eBus.messages.ERequestMessage; Step 1: Implement EReplier interface. public class CatalogReplier implements EReplier { private final EMessageKey mKey; private final FeedScope mScope; private EReplyFeed mFeed; private final List<EReplyFeed.ERequest> mRequests; public CatalogReplier(final String subject, final FeedScope scope) { mKey = new EMessageKey(com.acme.CatalogOrder.class, subject); mScope = scope; mRequests = new ArrayList<>(); } @Override public void startup() { try { Step 2: Open a reply feed for reply message key. May override EReplier interfaces methods. // This advertisement has no associated ECondition and uses EReplier interface method overrides. mFeed = (EReplyFeed.builder()).target(this) .messageKey(mKey) .scope(mScope) .build(); Step 3: Advertise reply feed. mFeed.advertise(); mFeed.updateFeedState(EFeedState.UP); } catch (IllegalArgumentException argex) { // Advertisement failed. Place recovery code here. } } Step 4: Wait for requests to arrive. @Override public void request(final EReplyFeed.ERequest request, final EReplyFeed feed) { final ERequestMessage msg = request.request(); try { mRequests.add(request); startOrderProcessing(msg, request); } catch (Exception jex) { request.reply(new CatalogOrderReply(ReplyStatus.ERROR, // reply status. jex.getMessage())); // reply reason. } } @Override public void cancelRequest(final EReplyFeed.ERequest request, final boolean mayRespond) { // Is this request still active? It is if the request is listed. if (mRequests.remove(request)) { // Yes, try to stop the request processing. try { // Throws an exception if the request cannot be stopped. stopOrderProcessing(request); } catch (Exception jex) { // Ignore since nothing else can be done. } } } Step 5: Send one or more reply messages back to requestor. public void orderReply(final EReplyFeed.ERequest request, final ReplyStatus status, final String reason) { final ERequestAd ad = mRequests.get(request); if (mRequests.contains(request) && request.isActive()) { request.reply((OrderReply.builder()).subject(mKey.subject()) .timestamp(Instant.now()) .replyStatus(status) .replyReason(reason) .build()); // If the request processing is complete, remove the request. if (status.isFinal()) { mRequests.remove(request); } } } @Override public void shutdown() { final String subject = mKey.subject(); // While eBus will does this for us, it is better to do it ourselves. for (EReplyFeed.ERequest request : mRequests) { request.reply((EReplyMessage.builder()).subject(subject) .timestamp(Instant.now()) .replyStatus(ReplyStatus.ERROR) .replyReason("shutting down") .build()); } mRequests.clear(); Step 6: When shutting down, either unadvertise or close reply feed. if (mFeed != null) { mFeed.close(); mFeed = null; } } }
- Author:
- Charles Rapp
- See Also:
EReplier
,ERequestor
,ERequestFeed
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
EReplyFeed.Builder
EReplyFeed.Builder
is now the preferred mechanism for creating aEReplyFeed
instance.static class
EReplyFeed.ERequest
-
Nested classes/interfaces inherited from class net.sf.eBus.client.EFeed
EFeed.AbstractClientTask, EFeed.FeedScope, EFeed.NotifyTask, EFeed.StatusTask<T extends IEFeed>
-
-
Field Summary
Fields Modifier and Type Field Description protected int
mActivationCount
Tracks the number of contra-feeds matched to this feed.protected net.sf.eBus.client.ESingleFeed.FeedType
mFeedType
Specifies whether this is a publish, subscribe, request, or reply feed.protected net.sf.eBus.client.ESubject
mSubject
The feed interfaces with this eBus subject.-
Fields inherited from class net.sf.eBus.client.EFeed
FEED_IS_INACTIVE, FEED_NOT_ADVERTISED, mEClient, mFeedId, mFeedState, mInPlace, mIsActive, mScope, NO_CONDITION, NOTIFY_METHOD, NULL_CLIENT
-
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description int
activationCount()
Returns the feed activation count.void
advertise()
Advertises this replier feed to the associated request subject.static EReplyFeed.Builder
builder()
Returns a newEReplyFeed
builder instance.protected void
inactivate()
If the advertisement is in place, then un-advertises it, sends a final error reply to all extant requests, and if this feed's scope is local & remote or remote only, removes this feed from the advertisers list.boolean
isAdvertised()
Returnstrue
if this reply feed is both open and advertised; otherwise returnsfalse
.EMessageKey
key()
Returns the feed message key.java.lang.String
messageSubject()
Returns the feedmessage key subect
.java.lang.String
toString()
Returns a containing the feed message key and data member values.void
unadvertise()
Retracts this replier feed from the associated request subject.void
updateFeedState(EFeedState update)
Updates the replier feed state to the given value.-
Methods inherited from class net.sf.eBus.client.EFeed
addAllKeys, addKey, addListener, checkScopes, clientId, clientName, close, createDispatcher, defaultDispatcher, eClient, equals, feedId, feedState, findKeys, findKeys, findKeys, hashCode, inPlace, isActive, isFeedUp, isOverridden, loadKeys, location, register, register, register, removeListener, scope, setExhaust, shutdown, shutdown, shutdownAll, startup, startup, startupAll, storeKeys, storeKeys, storeKeys, subclassDistance
-
-
-
-
Field Detail
-
mFeedType
protected final net.sf.eBus.client.ESingleFeed.FeedType mFeedType
Specifies whether this is a publish, subscribe, request, or reply feed.
-
mSubject
protected final net.sf.eBus.client.ESubject mSubject
The feed interfaces with this eBus subject. The subject type is based onfeed type
.
-
mActivationCount
protected int mActivationCount
Tracks the number of contra-feeds matched to this feed. If this is a publisher feed, then counts subscriber feeds. If a subscriber feed, then counts publisher feeds.
-
-
Method Detail
-
inactivate
protected void inactivate()
If the advertisement is in place, then un-advertises it, sends a final error reply to all extant requests, and if this feed's scope is local & remote or remote only, removes this feed from the advertisers list.- Specified by:
inactivate
in classEFeed
- See Also:
EFeed.close()
-
isAdvertised
public boolean isAdvertised()
Returnstrue
if this reply feed is both open and advertised; otherwise returnsfalse
.- Specified by:
isAdvertised
in interfaceIEReplyFeed
- Returns:
true
if this reply feed is open and advertised.
-
updateFeedState
public void updateFeedState(EFeedState update)
Updates the replier feed state to the given value. Ifupdate
equals the currently stored reply feed state, nothing is done. Otherwise, the updated value is stored. If this feed is advertised to the server and the subscription feed is up, then this update is forwarded to subscribed requestors.- Specified by:
updateFeedState
in interfaceIEReplyFeed
- Parameters:
update
- the new reply feed state.- Throws:
java.lang.NullPointerException
- ifupdate
isnull
.java.lang.IllegalStateException
- if this feed was closed and is inactive or is not advertised.
-
builder
public static EReplyFeed.Builder builder()
Returns a newEReplyFeed
builder instance. This instance should be used to build a single reply feed instance and not used to create multiple such feeds.- Returns:
- new reply feed builder.
-
advertise
public void advertise()
Advertises this replier feed to the associated request subject. If this feed is currently advertised to the subject, then does nothing.- Specified by:
advertise
in interfaceIEReplyFeed
- Throws:
java.lang.IllegalStateException
- if this feed is closed.- See Also:
unadvertise()
,updateFeedState(EFeedState)
,EFeed.close()
-
unadvertise
public void unadvertise()
Retracts this replier feed from the associated request subject. Does nothing if this feed is not currently advertised.- Specified by:
unadvertise
in interfaceIEReplyFeed
- Throws:
java.lang.IllegalStateException
- if this feed was closed and is inactive.- See Also:
advertise()
,EFeed.close()
-
toString
public java.lang.String toString()
Returns a containing the feed message key and data member values.
-
key
public final EMessageKey key()
Returns the feed message key. The message key type matches the feed type. If this is aEPublishFeed
, then anotification
message key is returned.- Returns:
- message key.
-
messageSubject
public final java.lang.String messageSubject()
Returns the feedmessage key subect
.- Returns:
- message key subject.
-
activationCount
public final int activationCount()
Returns the feed activation count.- Returns:
- value ≥ zero.
-
-