Axonframework: Implement Page and PageResponseType for QueryBus

Created on 29 Jan 2018  路  9Comments  路  Source: AxonFramework/AxonFramework

As a user of the QueryBus/QueryGateway the use case where you'd want to retrieve a Page<E> of a certain type makes sense. We should hence introduce a Page implementation which can be used as a ResponseType (introduced in #463) when performing a query.

Would Feature

All 9 comments

@abuijze / @m1l4n54v1c do we still want to introduce a PageResponseType as an implementation of the ResponseType interface to be used in the QueryBus?

think about to let user easier to custom it instead of writing a Page class? ex. user can use spring data Page interface or other class

Definitely a fair share @jokefaker, thanks for that! As it stands however, the ResponseType implementations Axon provide will likely ignore any generics added in an already existing Page implementation. Thus, this ticket is here to address the desire to be able to correctly consume such a ResponseType from the querying and query-result returning side.

If that will introduce an Axon specific Page class isn't clear to me yet, although I'd hope we could steer clear from that.

Sounds like a cool addition. It is going to be interesting to see how it will go together with subscription query though.

Do you have some idea (discussed) how to solve this issue?
I took a look at AbstractResponseType, it is maybe possible to provide an API to query a "paged" response without having strong dependency on Spring (Pageable/Page) or Google (Page) or etc.

So far, it is either a wrapper class around a page response or some custom implementation of AbstractResponseType that supports Page(from Spring)/etc on the client side code.

A bit more dirty solution to allow to define those ResponseType inside Axon code would be to use static lazy class providing static methods of response type to support Spring "Page" interface.
Using dynamic loading with classpath (throws if user calls the static method but does not have required classes on classpath)

We follow a similar pattern with wrappers classes as you're suggesting @Blackdread on the subscription query. We utilize project-reactor for that, but do not want to force users to pull in project-reactor if they're not using subscription queries.

If you want to have a go at this with a PR, your input is much appreciated. The current priority makes it so that it could take sometime until the Axon team will pick this up themselves.

I got a simple PageResponseType working (not tested a lot yet but does the job so far), just need to add custom serializer and deserializer as jackson is not correct by default for Pageable/Sort/etc.
See https://jira.spring.io/browse/DATACMNS-758 and https://jira.spring.io/browse/DATACMNS-1244

You are always more then welcome to contribute @Blackdread! Once you feel you are ready for it, we'll see the PR coming our way. And if not, then we will revert back to waiting until it pops up on our priority list.

Hi,

I also implemented my own PageResponseType, it is not at all ready for production, but maybe it can give some inspiration to someone in the same situation:

public class PageResponseType<R> extends AbstractResponseType<Page<R>> {


  /**
   * Instantiate a {@link ResponseType} with the given {@code expectedResponseType} as the type to be matched against and
   * to which the query response should be converted to, as is or as the contained type for an array/list/etc.
   *
   * @param expectedResponseType the response type which is expected to be matched against and to be returned, as is or as
   *                             the contained type for an array/list/etc
   */
  @JsonCreator
  @ConstructorProperties({"expectedResponseType"})
  public PageResponseType(@JsonProperty("expectedResponseType") Class<R> expectedResponseType) {
    super(expectedResponseType);
  }

  @Override
  public boolean matches(Type responseType) {
    Type unwrapped = ReflectionUtils.unwrapIfType(responseType, Future.class, Page.class);
    return isGenericAssignableFrom(unwrapped) || isAssignableFrom(unwrapped);
  }

  @Override
  public Page<R> convert(Object response) {
    return (Page<R>) response;
  }

  @Override
  public Class responseMessagePayloadType() {
    return Page.class;
  }

  @Override
  public String toString() {
    return "PageResponseType{" + expectedResponseType + "}";
  }

}
Was this page helpful?
0 / 5 - 0 ratings