Class InterceptingQueryBus
- All Implemented Interfaces:
DescribableComponent,QueryBus,QueryHandlerRegistry<QueryBus>
QueryBus wrapper that supports both MessageHandlerInterceptors and
MessageDispatchInterceptors. Actual dispatching and handling of queries is done by
a delegate.
This InterceptingQueryBus is typically registered as a
decorator and automatically kicks in whenever
QueryMessage specific MessageHandlerInterceptors or any MessageDispatchInterceptors are
present.
- Since:
- 5.0.0
- Author:
- Allard Buijze, Mateusz Nowak, Steven van Beelen
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final int -
Constructor Summary
ConstructorsConstructorDescriptionInterceptingQueryBus(QueryBus delegate, List<MessageHandlerInterceptor<? super QueryMessage>> handlerInterceptors, List<MessageDispatchInterceptor<? super QueryMessage>> dispatchInterceptors, List<MessageDispatchInterceptor<? super SubscriptionQueryUpdateMessage>> updateDispatchInterceptors) Constructs aInterceptingQueryBus, delegating dispatching and handling logic to the givendelegate. -
Method Summary
Modifier and TypeMethodDescriptioncompleteSubscriptions(Predicate<QueryMessage> filter, ProcessingContext context) Completessubscription queriesmatching the givenfilter.completeSubscriptionsExceptionally(Predicate<QueryMessage> filter, Throwable cause, ProcessingContext context) voiddescribeTo(ComponentDescriptor descriptor) Describe the properties ofthis DescribableComponentwith the givendescriptor.emitUpdate(Predicate<QueryMessage> filter, Supplier<SubscriptionQueryUpdateMessage> updateSupplier, ProcessingContext context) Emits the outcome of theupdateSuppliertosubscription queriesmatching the givenqueryNameand givenfilter.query(QueryMessage query, ProcessingContext context) Dispatch the givenqueryto aQueryHandlersubscribedto the givenquery'squery name, returning aMessageStreamofresponsesto the givenquery.subscribe(QualifiedName queryName, QueryHandler queryHandler) subscribeToUpdates(QueryMessage query, int updateBufferSize) Subscribes the givenquerywith the givenupdateBufferSize, and returns the MessageStream that provides the update of the subscription query.subscriptionQuery(QueryMessage query, ProcessingContext context, int updateBufferSize) Dispatch the givenqueryto a single QueryHandler subscribed to the givenquery's queryName/initialResponseType/updateResponseType.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface org.axonframework.messaging.queryhandling.QueryHandlerRegistry
subscribe, subscribe
-
Field Details
-
DECORATION_ORDER
public static final int DECORATION_ORDERThe order in which theInterceptingQueryBusis applied as adecoratorto theQueryBus.As such, any decorator with a lower value will be applied to the delegate, and any higher value will be applied to the
InterceptingQueryBusitself. Using the same value can either lead to application of the decorator to the delegate or theInterceptingQueryBus, depending on the order of registration.The order of the
InterceptingQueryBusis set toInteger.MIN_VALUE + 100to ensure it is applied very early in the configuration process, but not the earliest to allow for other decorators to be applied.- See Also:
-
-
Constructor Details
-
InterceptingQueryBus
public InterceptingQueryBus(@Nonnull QueryBus delegate, @Nonnull List<MessageHandlerInterceptor<? super QueryMessage>> handlerInterceptors, @Nonnull List<MessageDispatchInterceptor<? super QueryMessage>> dispatchInterceptors, @Nonnull List<MessageDispatchInterceptor<? super SubscriptionQueryUpdateMessage>> updateDispatchInterceptors) Constructs aInterceptingQueryBus, delegating dispatching and handling logic to the givendelegate. The givenhandlerInterceptorsare wrapped around thequery handlerswhen subscribing. The givendispatchInterceptorsare invoked before dispatching is provided to the givendelegate. The givenupdateDispatchInterceptorsare invoked before emitting subscription query update.- Parameters:
delegate- The delegateQueryBusthat will handle all dispatching and handling logic.handlerInterceptors- The interception to invoke before handling a query and if present on the query result.dispatchInterceptors- The interception to invoke before dispatching a query and on the query result.updateDispatchInterceptors- The interception to invoke before emitting subscription query update.
-
-
Method Details
-
subscribe
public InterceptingQueryBus subscribe(@Nonnull QualifiedName queryName, @Nonnull QueryHandler queryHandler) Description copied from interface:QueryHandlerRegistrySubscribe the givenqueryHandlerforqueriesandresponseof the givenqueryName.If a subscription already exists for the
queryName, the behavior is undefined. Implementations may throw an exception to refuse duplicate subscription or alternatively decide whether the existing or newhandlergets the subscription.- Specified by:
subscribein interfaceQueryHandlerRegistry<QueryBus>- Parameters:
queryName- The fully qualified name of the queryqueryHandler- The handler instance that handlesqueriesfor the given queryName.- Returns:
- This registry for fluent interfacing.
-
query
@Nonnull public MessageStream<QueryResponseMessage> query(@Nonnull QueryMessage query, @Nullable ProcessingContext context) Description copied from interface:QueryBusDispatch the givenqueryto aQueryHandlersubscribedto the givenquery'squery name, returning aMessageStreamofresponsesto the givenquery.The resulting
MessageStreamwill contain 0, 1, or NQueryResponseMessages, depending on theQueryHandlerthat handled the givenquery.As several
QueryHandlerscan be registered for the same query name, this method will loop through them (in insert order) until one has a suitable return value. A suitable response is any value or user exception returned from aQueryHandler. When no handlers are available that can answer the givenquery, the returnedMessageStreamwill havefailedwith aNoHandlerForQueryException.- Specified by:
queryin interfaceQueryBus- Parameters:
query- The query to dispatch.context- The processing context under which the query is being published (can benull).- Returns:
- A
MessageStreamcontaining either 0, 1, or NQueryResponseMessages.
-
subscriptionQuery
@Nonnull public MessageStream<QueryResponseMessage> subscriptionQuery(@Nonnull QueryMessage query, @Nullable ProcessingContext context, int updateBufferSize) Description copied from interface:QueryBusDispatch the givenqueryto a single QueryHandler subscribed to the givenquery's queryName/initialResponseType/updateResponseType. The result is lazily created and there will be no execution of the query handler before there is a subscription to the initial result. In order not to miss update, the query bus will queue all update which happen after the subscription query is done and once the subscription to the flux is made, these update will be emitted.If there is an error during retrieving or consuming initial result, stream for incremental update is NOT interrupted.
If there is an error during emitting an update, subscription is cancelled causing further emits not reaching the destination.
If a subscription query with the same
queryidentifier is already registered, the returnedMessageStreamwill befailedwith aSubscriptionQueryAlreadyRegisteredExceptioninstead of throwing the exception. This allows callers to handle double subscription scenarios gracefully through the stream API.- Specified by:
subscriptionQueryin interfaceQueryBus- Parameters:
query- The subscription query to dispatch.context- The processing context under which the query is being published (can benull).updateBufferSize- The size of the buffer which accumulates update.- Returns:
- query result containing initial result and incremental update, or a failed
MessageStreamwithSubscriptionQueryAlreadyRegisteredExceptionif a subscription with the same query identifier already exists.
-
subscribeToUpdates
@Nonnull public MessageStream<SubscriptionQueryUpdateMessage> subscribeToUpdates(@Nonnull QueryMessage query, int updateBufferSize) Description copied from interface:QueryBusSubscribes the givenquerywith the givenupdateBufferSize, and returns the MessageStream that provides the update of the subscription query.Can be used directly instead when fine-grained control of update handlers is required. If using the update directly is not mandatory for your use case, we strongly recommend using
QueryBus.subscriptionQuery(QueryMessage, ProcessingContext, int)instead.Note that the returned MessageStream must be consumed from before the buffer fills up. Once the buffer is full, any attempt to add an update will complete the stream with an exception.
If a subscription query with the same
queryidentifier is already registered, the returnedMessageStreamwill befailedwith aSubscriptionQueryAlreadyRegisteredExceptioninstead of throwing the exception.- Specified by:
subscribeToUpdatesin interfaceQueryBus- Parameters:
query- The subscription query for which we register an update handler.updateBufferSize- The size of the buffer that accumulates update.- Returns:
- a MessageStream of update for the given subscription query, or a failed
MessageStreamwithSubscriptionQueryAlreadyRegisteredExceptionif a subscription with the same query identifier already exists.
-
emitUpdate
@Nonnull public CompletableFuture<Void> emitUpdate(@Nonnull Predicate<QueryMessage> filter, @Nonnull Supplier<SubscriptionQueryUpdateMessage> updateSupplier, @Nullable ProcessingContext context) Description copied from interface:QueryBusEmits the outcome of theupdateSuppliertosubscription queriesmatching the givenqueryNameand givenfilter.- Specified by:
emitUpdatein interfaceQueryBus- Parameters:
filter- A predicate filtering onQueryMessages. TheupdateSupplierwill only be sent to subscription queries matching this filter.updateSupplier- The update supplier to emit forsubscription queriesmatching the givenfilter.context- The processing context under which the updateSupplier is being emitted (can benull).- Returns:
- A future completing whenever the updateSupplier has been emitted.
-
completeSubscriptions
@Nonnull public CompletableFuture<Void> completeSubscriptions(@Nonnull Predicate<QueryMessage> filter, @Nullable ProcessingContext context) Description copied from interface:QueryBusCompletessubscription queriesmatching the givenfilter.To be used whenever there are no subsequent update to
emitleft.- Specified by:
completeSubscriptionsin interfaceQueryBus- Parameters:
filter- A predicate filtering onQueryMessages. Subscription queries matching this filter will be completed.context- The processing context within which to complete subscription queries (can benull).- Returns:
- A future completing whenever all matching
subscription querieshave been completed.
-
completeSubscriptionsExceptionally
@Nonnull public CompletableFuture<Void> completeSubscriptionsExceptionally(@Nonnull Predicate<QueryMessage> filter, @Nonnull Throwable cause, @Nullable ProcessingContext context) Description copied from interface:QueryBusCompletessubscription queriesmatching the givenfilterexceptionally with the givencause.To be used whenever
emitting updateshould be stopped due to some exception.- Specified by:
completeSubscriptionsExceptionallyin interfaceQueryBus- Parameters:
filter- A predicate filtering onQueryMessages. Subscription queries matching this filter will be completed exceptionally.cause- the cause of an errorcontext- The processing context within which to complete subscription queries exceptionally (can benull).- Returns:
- A future completing whenever all matching
subscription querieshave been completed exceptionally.
-
describeTo
Description copied from interface:DescribableComponentDescribe the properties ofthis DescribableComponentwith the givendescriptor.Components should call the appropriate
describePropertymethods on the descriptor to register their properties. The descriptor is responsible for determining how these properties are formatted and structured in the final output.Best Practices: As a general rule, all relevant fields of a
DescribableComponentimplementation should be described in this method. However, developers have discretion to include only the fields that make sense in the context. Not every field may be meaningful for description purposes, especially internal implementation details. Furthermore, components might want to expose different information based on their current state. The final decision on what properties to include lies with the person implementing thedescribeTomethod, who should focus on providing information that is useful for understanding the component's configuration and state.Example implementation:
public void describeTo(ComponentDescriptor descriptor) { descriptor.describeProperty("name", this.name); descriptor.describeProperty("enabled", this.enabled); descriptor.describeProperty("configuration", this.configuration); // A nested component descriptor.describeProperty("handlers", this.eventHandlers); // A collection }- Specified by:
describeToin interfaceDescribableComponent- Parameters:
descriptor- The component descriptor to describethis DescribableComponentn its properties in.
-