Skip to content

Commit

Permalink
XWIKI-21809: ClassCastException in DefaultEventConverterManager on a …
Browse files Browse the repository at this point in the history
…cluster environment (#2929)

  * Some task output is Optional and we never want the Optional in the
    notification data: we do want what the Optional contains.
  * Prevent entirely notification to be sent if output is Optional and
    return is empty

(cherry picked from commit e877bcc)
  • Loading branch information
surli committed Feb 27, 2024
1 parent afa3a64 commit 62a2a43
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -442,41 +442,53 @@ private <O, I> void complete(EventStoreTask<O, I> task, O output)
task.future.complete(output);

// Notify event listeners
switch (task.type) {
case DELETE_EVENT:
this.observation.notify(new EventStreamDeletedEvent(), task.output);
break;
Object notificationOuput = task.output;
boolean skipNotify = false;
if (task.output instanceof Optional<?>) {
Optional<?> optionalOutput = (Optional<?>) task.output;
if (optionalOutput.isPresent()) {
notificationOuput = optionalOutput.get();
} else {
skipNotify = true;
}
}
if (!skipNotify) {
switch (task.type) {
case DELETE_EVENT:
this.observation.notify(new EventStreamDeletedEvent(), notificationOuput);
break;

case DELETE_EVENT_BY_ID:
this.observation.notify(new EventStreamDeletedEvent(), task.output);
break;
case DELETE_EVENT_BY_ID:
this.observation.notify(new EventStreamDeletedEvent(), notificationOuput);
break;

case SAVE_EVENT:
this.observation.notify(new EventStreamAddedEvent(), task.output);
break;
case SAVE_EVENT:
this.observation.notify(new EventStreamAddedEvent(), notificationOuput);
break;

case DELETE_STATUS:
this.observation.notify(new EventStatusDeletedEvent(), task.output);
break;
case DELETE_STATUS:
this.observation.notify(new EventStatusDeletedEvent(), notificationOuput);
break;

case DELETE_STATUSES:
this.observation.notify(new EventStatusDeletedEvent(), null);
break;
case DELETE_STATUSES:
this.observation.notify(new EventStatusDeletedEvent(), null);
break;

case SAVE_STATUS:
this.observation.notify(new EventStatusAddOrUpdatedEvent(), task.output);
break;
case SAVE_STATUS:
this.observation.notify(new EventStatusAddOrUpdatedEvent(), notificationOuput);
break;

case DELETE_MAIL_ENTITY:
this.observation.notify(new MailEntityDeleteEvent(), task.output);
break;
case DELETE_MAIL_ENTITY:
this.observation.notify(new MailEntityDeleteEvent(), notificationOuput);
break;

case SAVE_MAIL_ENTITY:
this.observation.notify(new MailEntityAddedEvent(), task.output);
break;
case SAVE_MAIL_ENTITY:
this.observation.notify(new MailEntityAddedEvent(), notificationOuput);
break;

default:
break;
default:
break;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,24 @@
import org.xwiki.eventstream.EventSearchResult;
import org.xwiki.eventstream.EventStatus;
import org.xwiki.eventstream.EventStreamException;
import org.xwiki.eventstream.events.EventStreamAddedEvent;
import org.xwiki.eventstream.events.MailEntityAddedEvent;
import org.xwiki.eventstream.events.MailEntityDeleteEvent;
import org.xwiki.observation.ObservationManager;
import org.xwiki.test.junit5.mockito.ComponentTest;
import org.xwiki.test.junit5.mockito.InjectComponentManager;
import org.xwiki.test.junit5.mockito.InjectMockComponents;
import org.xwiki.test.junit5.mockito.MockComponent;
import org.xwiki.test.mockito.MockitoComponentManager;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;

/**
* Validate {@link AbstractAsynchronousEventStore}.
Expand Down Expand Up @@ -265,6 +273,9 @@ protected Optional<Event> syncDeleteEvent(Event event) throws EventStreamExcepti
@InjectMockComponents
private TestAbstractAsynchronousEventStore store;

@MockComponent
private ObservationManager observation;

private DefaultEvent event(String id)
{
DefaultEvent event = new DefaultEvent();
Expand Down Expand Up @@ -404,12 +415,22 @@ void mailentity() throws InterruptedException, ExecutionException, EventStreamEx
assertSame(status21, this.store.events.get(event2.getId()).mailstatuses.get(status21.getEntityId()));
assertSame(status24, this.store.events.get(event2.getId()).mailstatuses.get(status24.getEntityId()));

verify(this.observation).notify(any(EventStreamAddedEvent.class), eq(event1));
verify(this.observation).notify(any(EventStreamAddedEvent.class), eq(event2));
verify(this.observation).notify(any(MailEntityAddedEvent.class), eq(status11));
verify(this.observation).notify(any(MailEntityAddedEvent.class), eq(status13));
verify(this.observation).notify(any(MailEntityAddedEvent.class), eq(status21));
verify(this.observation).notify(any(MailEntityAddedEvent.class), eq(status24));


this.store.deleteMailEntityEvent(status11).get();

assertNull(this.store.events.get(event1.getId()).mailstatuses.get(status11.getEntityId()));
assertSame(status13, this.store.events.get(event1.getId()).mailstatuses.get(status13.getEntityId()));
assertSame(status21, this.store.events.get(event2.getId()).mailstatuses.get(status21.getEntityId()));
assertSame(status24, this.store.events.get(event2.getId()).mailstatuses.get(status24.getEntityId()));

verify(this.observation).notify(any(MailEntityDeleteEvent.class), eq(status11));
}

@Test
Expand Down

0 comments on commit 62a2a43

Please sign in to comment.