官术网_书友最值得收藏!

  • Java EE 8 and Angular
  • Prashant Padmanabhan
  • 496字
  • 2021-07-02 19:22:35

Ordered events

This basically orders the observers using the @Priority annotation. This feature can be made use of when there are multiple observer methods and you need to control which ones are called first and which ones are called later:

  • The lowest value would be the first observer method that gets called
  • The highest value would be called last
  • If there's no priority specified then this event will be considered mid-range priority
  • For observer methods with the same priority, the ordering is undefined
  • No priority is applicable for asynchronous events, since they're not sequential

The usage of the ordered event is shown here:

public void observer1(@Observes @Priority(1) Payload event) { }
public void observer2 (@Observes @Priority(2) Payload event) { }

Given the behavior of ordered events using @Priority, along with the mutable state of the payload, one could utilize this feature for certain use cases. Consider a fairly common scenario in which the system should lock the user account based on the number of failed login attempts. Additionally, send out a notification to the user, such as an SMS, if the account gets locked in the process. In this case, we could define two ordered observers for this type of event, with the first observer checking for failed attempts and setting the lock status on the payload object. The second observer would then be able to see the changes made to the payload by the first observer and thus, based on this change in status, it would send the notification. Let us see, how this can be tackled in the sample code explained next.

A login service will raise a LoginEvent containing a user's ID and attempt count. Take a look at the LoginEvent code:

public class LoginEvent {
private final Integer attemptsMade;
private final String userId;
private boolean lockAccount = false;

public LoginEvent(Integer count, String userId) {
this.attemptsMade = count;
this.userId = userId;
}
...
}

The relevant code snippet for the AccountService, a class responsible for signing in the user and raising an event, is shown here:

@Inject private Event<LoginEvent> event;

/* A login method on this class, raises the event for failed login attempts using below line. */
event.fire(new LoginEvent(attemptsMadeCount, byUserId ));

The first observer is responsible for checking and locking the account based on attempts made:

public class MonitorAccountAccess {
public static final Integer MAX_ATTEMPTS = 3;

public void lockForFailedAttempts(
@Observes @Priority(1) LoginEvent event) {
if(event.getAttemptsMade() >= MAX_ATTEMPTS) {
event.setLockAccount(true);
//do more work to push status in database
}
}
}

The second observer is responsible for sending an SMS when an account gets locked. This code relies on the lock account status update being changed in the MonitorAccountAccess code block:

public class AccountLockNotification {

public void sendSmsOnAccountLock(@Observes @Priority(2) LoginEvent event) {
if(event.isLockAccount() == false) return;
sendAccountLockSms(event.getUserId());
}
}

When the event is fired synchronously from the AccountService code, MonitorAccountAccess will be called first, as it has @Priority(1). Later, the AccountLockNotification code gets called, along with @Priority(2) and the updated LoginEvent object.

主站蜘蛛池模板: 新兴县| 永寿县| 鹰潭市| 凤翔县| 商洛市| 井研县| 茂名市| 灯塔市| 安西县| 浦城县| 新和县| 登封市| 拜泉县| 剑阁县| 吴江市| 蓬安县| 通渭县| 普洱| 利辛县| 通山县| 洮南市| 德州市| 郴州市| 赤壁市| 南乐县| 林州市| 封丘县| 海门市| 军事| 栾城县| 遵义县| 永宁县| 维西| 桂东县| 无为县| 郧西县| 太和县| 伊金霍洛旗| 丰都县| 吴堡县| 玛曲县|