Spring Data REST / Spring Data Commons Доменные события
Я прочитал этот блог и этот справочный материал и определил, что события домена Spring Data Commons не работают при применении в событиях Spring Data REST AbstractRepositoryEventListener (т. Е. OnBeforeSave, onAfterDelete и т. Д.).
Человек:
@Entity @Data @EqualsAndHashCode(callSuper=true)
public class Person extends AbstractEntity {
// impl
public void markComplete(){
registerEvent(new PersonCompletedEvent());
}
}
PersonCompletedEvent:
@Data public class PersonCompletedEvent {} // the RestBucks sample does not have OrderPaid event extend ApplicationEvent, I tried both ways and it still doesn't work.
Обновление: прочитайте комментарий в PersonHandler, это причина, по которой события приложения не работают в этом примере.
PersonHandler:
@Component @RepositoryEventHandler public class PersonHandler {
@PersistenceContext private EntityManager entityManager;
@Autowired private PersonRepo personRepo;
@HandleBeforeSave public void beforeSave(Person afterPerson){
/* UPDATE ::: This is the problem.
* This line is the reason why applicatin events do not fire.
* I need the before entity to detect delta's in the domain
* so I must detach it. However this causes events to be dropped.
*
* What's the best way to get the previous state?
*/
entityManager.detach(afterPerson);
Person beforePerson = personRepo.findOne(afterPerson.getId());
// impl
if (some condition) {
afterPerson.markComplete(); // this does add the event but it's never fired.
}
}
}
AbstractEntity:
import org.springframework.data.domain.AbstractAggregateRoot;
@MappedSuperclass @Data @EntityListeners(AuditingEntityListener.class)
public abstract class AbstractEntity extends AbstractAggregateRoot implements Identifiable<Long> {
// impl
}
PersonListener:
public class PersonListener {
@EventListener
public void processCompleted(PersonCompletedEvent event) {
// THIS IS NEVER FIRED
}
}
Я подробно отлаживал это, и похоже, что Domain Events теряются где-то между RepositoryEntityController и EventPublishingRepositoryProxyPostProcessor$EventPublishingMethodInterceptor.
На самом деле происходит то, что другой экземпляр моей сущности фактически перехватывается, и в этот момент Domain Events больше не существует. Я могу подтвердить, что @AfterDomainEventPublication clearDomainEvents() НЕ вызывается в это время, что наводит меня на мысль, что это как-то связано с переходным процессом domainEvents.
RepositoryEntityController в Spring Data REST выглядит следующим образом:
private ResponseEntity<ResourceSupport> saveAndReturn(Object domainObject, RepositoryInvoker invoker,
HttpMethod httpMethod, PersistentEntityResourceAssembler assembler, boolean returnBody) {
publisher.publishEvent(new BeforeSaveEvent(domainObject)); // 1
Object obj = invoker.invokeSave(domainObject); // 2
publisher.publishEvent(new AfterSaveEvent(obj));
После выполнения строки, прокомментированной с 1, мой domainObject имеет domainEvents, и это то, что входит в строку, прокомментированную с 2, invokeSave. Когда моя точка останова перехватывает RepositoryEntityController и EventPublishingRepositoryProxyPostProcessor$EventPublishingMethodInterceptor, это фактически другой экземпляр моего объекта (другой идентификатор объекта), и единственное, чего не хватает, это domainEvents и ничего не запускается.
Обновление: прочитайте мой комментарий ниже, он не работает, потому что объект отсоединен.