2017-12-30 65 views
0

Ich habe Probleme beim Veröffentlichen von Ereignissen von einem Aggregat-Stamm in einer Spring Boot-Anwendung. Was ich grundsätzlich möchte, ist ein "Update" -Ereignis jedes Mal zu veröffentlichen, wenn einige Informationen über eine Person geändert werden. Der Code dafür ist ziemlich einfach:Spring Datendomänenereignisse fehlen (?)

@Entity 
public class Person { 
    @Transient 
    private final Collection<AbstractPersonRelatedEvent> events = new ArrayList<>(); 

    Person(Person other) { 
    // copy other fields 
    other.events.foreach(events::add); 
    } 

    // other stuff 

    public Person updateInformation(...) { 
    Person updated = new Person(this); 

    // setting new data on the updated person 

    if (!hasUpdateEventRegistered()) { 
     updated.registerEvent(PersonDataUpdatedEvent.forPerson(updated)); 
    } 
    return updated; 
    } 

    void registerEvent(AbstractPersonRelatedEvent event) { 
    events.add(event); 
    } 

    @DomainEvents 
    Collection<AbstractPersonRelatedEvent> getModificationEvents() { 
    return Collections.unmodifiableCollection(events); 
    } 

    @AfterDomainEventPublication 
    void clearEvents() { 
    events.clear(); 
    } 
} 

ich Person Instanzen durch einen Manager leite:

@Service 
@Transactional 
class PersistentPersonManager implements PersonManager { 

// other methods are omitted 

    @Override 
    public Person save(Person person) { 
    return personRepository.save(person); 
    } 

} 

Allerdings, wenn ich den Manager nennen (manager.save(person.updateInformation(...)) die Ereignisse scheinen "fehlenden" zu gehen: Beim Aufrufen der save()-Methode sind alle Ereignisse noch vorhanden, aber wenn Spring getModificationEvents() aufruft, ist die Sammlung leer. Die Ereignisse scheinen irgendwo dazwischen verschwunden zu sein (wobei nur Spring-Code ausgeführt wird.)

Da dies ziemlich einfach ist, muss ich etwas Wesentliches vermissen, aber bin in einer Furche stecken geblieben.

Also, wie komme ich hier wieder zurück?

Antwort

1

Ich nehme an, dass Sie hier JPA verwenden.

Für JPA die save Operation tatsächlich eine merge auf der JPA EnityManager.

Für eine getrennte Entität merge lädt/findet die Entität mit derselben ID aus der Datenbank oder der aktuellen Sitzung und kopiert alle (geänderten) Felder um. Dadurch werden vorübergehende Felder wie die Ereignisse ignoriert.

Sie arbeiten mit getrennten Entitäten, weil Sie bei jedem Aufruf eine neue Entität erstellen updateInformation.

So, hier ist was passiert:

  1. Sie eine Einheit laden (e1) aus der Datenbank. Es sind keine Ereignisse registriert.

  2. Wenn Sie updateInformation aufrufen, erstellen Sie eine neue abgetrennte Entität (e2). Sie registrieren Ereignisse auch mit e2.

  3. Wenn save JPA Aufruf findet die e1 und kopiert alle Änderungen von e2 in sie passend, mit Ausnahme der Ereignisse. So hat e1 noch keine Ereignisse registriert.

  4. Ereignisse werden ausgelöst, aber es gibt keine, weil nur e1 verwendet wird.

Um dieses Problem zu beheben: Erstellen Sie keine neue Instanzen der Entität in updateInformation.