Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@Subscribe-r of the rejection caused by a particular command causes the dispatching failure in some cases #1318

Closed
armiol opened this issue Nov 10, 2020 · 0 comments · Fixed by #1343
Assignees

Comments

@armiol
Copy link
Contributor

armiol commented Nov 10, 2020

Landscape

It is possible to subscribe to a rejection which is caused by some command:

public class CancellationWatch extends AbstractEventSubscriber {

    @Subscribe
    void on(Rejections.OrderAlreadyCompleted r, CancelOrder c) {
        ...
    }
}

In this example, a subscriber wants to consume only those OrderAlreadyCompleted rejections which are thrown while handling order cancellations (hence, CancelOrder command is the second argument).

At the same time, it is also possible to declare several command handlers which would throw a rejection of the same type:

public class OrderAggregate extends Aggregate<OrderId, Order, Order.Builder> {

    @Assign
    OrderCompleted handle(CompleteOrder c) throws OrderAlreadyCompleted {
        ...
    }

    @Assign
    OrderCancelled handle(CancelOrder c) throws OrderAlreadyCompleted {
        ...
    }
}

In the example above, the OrderAggregate rejects all commands with OrderAlreadyCompleted if the order is already completed.

Action

Now, if some completed order handles CompleteOrder command, the aggregate throws a OrderAlreadyCompleted rejection. In theory, if anyone has subscribed to this rejection, they would receive it.

But, one thing for sure, CancellationWatch is not interested in this rejection—because the origin command is not what it expects.

So if no subscribers to OrderAlreadyCompleted rejection is found, it should just pass through the event bus, just as any other rejection or event.

Issue

In reality, the framework attempts to select the handler for this rejection anyway, and fails to do so:

java.lang.IllegalStateException: Unable to find handler with the key: DispatchKey{messageClass=`com.acme.order.Rejections$OrderAlreadyCompleted}.
	at com.google.common.base.Preconditions.checkState(Preconditions.java:589)
	at io.spine.server.model.HandlerMap.handlersOf(HandlerMap.java:145)
	at io.spine.server.model.HandlerMap.handlersOf(HandlerMap.java:174)
	at io.spine.server.event.model.EventReceivingClassDelegate.handlersOf(EventReceivingClassDelegate.java:127)
	at io.spine.server.event.model.EventSubscriberClass.subscribersOf(EventSubscriberClass.java:79)
	at io.spine.server.event.model.SubscribingClass.subscriberOf(SubscribingClass.java:47)
	at io.spine.server.event.AbstractEventSubscriber.canDispatch(AbstractEventSubscriber.java:140)
	at io.spine.server.event.AbstractEventSubscriber.canDispatch(AbstractEventSubscriber.java:60)
	at io.spine.server.bus.DispatcherRegistry.lambda$dispatchersOf$0(DispatcherRegistry.java:105)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:174)
	at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1556)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:566)
	at io.spine.server.bus.DispatcherRegistry.dispatchersOf(DispatcherRegistry.java:107)
	at io.spine.server.bus.DeadMessageFilter.filter(DeadMessageFilter.java:56)
	at io.spine.server.bus.FilterChain.filter(FilterChain.java:57)
	at io.spine.server.bus.Bus.filter(Bus.java:296)
	at io.spine.server.bus.Bus.filter(Bus.java:272)
	at io.spine.server.bus.Bus.filterAndPost(Bus.java:150)
	at io.spine.server.bus.Bus.post(Bus.java:146)

The reason is as follows. From the dispatcher registry, the framework knows that someone does handle the rejections of this type. And from this point, it is going to get that someone. There is no option to discover that in fact that "someone" does not match the "origin message" criterion.

@armiol armiol changed the title @Subscriber of the rejection caused by a particular command causes the dispatching failure in some cases @Subscriber of the rejection caused by a particular command causes the dispatching failure in some cases Nov 10, 2020
@armiol armiol changed the title @Subscriber of the rejection caused by a particular command causes the dispatching failure in some cases @Subscribe-r of the rejection caused by a particular command causes the dispatching failure in some cases Nov 10, 2020
@yuri-sergiichuk yuri-sergiichuk self-assigned this Dec 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants