#spring-boot #cqrs #axon
Вопрос:
У меня есть агрегированный корень,подобный этому, это агрегаты creaditcard, в которых есть записи о платежах и идентификатор, перечисление
@NoArgsConstructor
@EqualsAndHashCode
@Log4j2
@Aggregate
public class CreditCard {
@AggregateIdentifier
private String id;
@AggregateMember
private List<CreditCardTransaction> transactions= new ArrayList<>();
private int limit;
@CommandHandler
public CreditCard(CreditCardCreatedCmd cmd) {
log.info(cmd.getId() "," cmd.getLimit());
AggregateLifecycle.apply(new CreditCardCreatedEvt(cmd.getId(), cmd.getLimit()));
}
@EventSourcingHandler
public void on(CreditCardCreatedEvt evt) {
id = evt.getId();
limit = evt.getLimit();
log.info("[CreditCardCreatedEvt] id : " id);
}
@CommandHandler
public void on(PaymentCmd cmd) throws LimitExceededException {
if (limit < cmd.getValue())
throw new LimitExceededException();
AggregateLifecycle.apply(new PaymentSuccessEvt(UUID.randomUUID().toString(), cmd.getValue()));
}
@EventSourcingHandler
public void handle(PaymentSuccessEvt evt) {
log.info("[PaymentSuccessEvt] transactionId : " evt.getTransactionId());
transactions.add(new CreditCardTransaction(evt.getTransactionId(), evt.getValue()));
}
}
и дочерняя организация, у которой есть запись о платеже
@Log4j2
@NoArgsConstructor
public class CreditCardTransaction {
@EntityId
private String transactionId;
private int transactionValue;
private boolean refund = false;
private LocalDateTime paymentDate;
public CreditCardTransaction(String transactionId, int transactionValue) {
this.transactionId = transactionId;
this.transactionValue = transactionValue;
this.paymentDate = LocalDateTime.now();
}
public String getTransactionId() {
return transactionId;
}
@CommandHandler
public void on(RefundCmd cmd) {
if (ChronoUnit.DAYS.between(paymentDate, cmd.getToday()) >= 30)
throw new DueTimeOverException();
log.info("[RefundCmd] " cmd.getTransactionId());
AggregateLifecycle.apply(new RefundEvt(cmd.getCardId(), cmd.getTransactionId()));
}
@EventSourcingHandler
public void hanlde(RefundEvt evt) {
if (transactionId.equals(evt.getTransactionId())) {
transactionValue*=-1;
paymentDate=LocalDateTime.now();
refund = true;
log.info("[RefundEvt accepted] transactionId : " transactionId);
}
log.info("[RefundEvt rejected] transactionId : " transactionId);
}
}
@Data@NoArgsConstructor@AllArgsConstructor
public class RefundCmd {
@TargetAggregateIdentifier
String cardId;
String transactionId;
LocalDateTime today;
}
@Data@NoArgsConstructor
public class RefundEvt {
String cardId;
String transactionId;
LocalDateTime today;
public RefundEvt(String cardId, String transactionId) {
this.cardId = cardId;
this.transactionId = transactionId;
today=LocalDateTime.now();
}
}
когда я отправляю команду своему дочернему объекту, как это
commandGateway.send(new RefundCmd(cardId, transactionId,LocalDateTime.now()));
обработчик команд этой дочерней сущности работает, но eventsourcinghandler не может получить событие
и у меня есть исключение, как показано ниже
Command 'com.cqrs.order.demo.command.RefundCmd' resulted in org.axonframework.commandhandling.CommandExecutionException(Cannot request current Scope if none is
active)
Я делаю это со ссылкой на это.
Комментарии:
1. Вероятно, вам нужно изменить имя идентификатора aggregate, чтобы оно соответствовало имени в aggregate и команде. Либо назовите его CardID в совокупности, либо назовите его id в RefundCmd.
2. спасибо за ответ, но это не работает
Ответ №1:
при публикации событий используйте org.axonframework.modelling.command.AggregateLifecycle.apply
не org.axonframework.commandhandling.model.AggregateLifecycle.apply
Комментарии:
1. Была ли у вас зависимость от старой версии AxonFramework?