Class Queryable

java.lang.Object
org.apache.juneau.rest.server.converter.Queryable
All Implemented Interfaces:
RestConverter

public class Queryable extends Object implements RestConverter
Converter for enabling search/view/sort/paging support on response objects returned by a @RestOp-annotated method, backed by the BeanQuery engine.

When enabled, a response that's a Collection or object array of beans, or of Maps, can be filtered with the BeanQuery search language via the following request parameters (see BeanQueryRequest for the per-parameter Swagger docs):

  • &search= Comma-separated column=expression clauses.
  • &view= Comma-separated columns to return, in order.
  • &sort= Comma-separated sort columns; append ":desc" (or "-") for descending.
  • &position= 0-based index of the first row.
  • &limit= Maximum rows to return.
  • &opts= Options as key=value clauses (e.g. counts=true).

A response that isn't tabular — not a Collection or object array, or one whose first non-null element is a plain string, number, date or other scalar — is returned unchanged; the query parameters are ignored, exactly as they were for non-tabular results before 10.0. An empty or all-null collection is likewise returned unchanged (there's no element to derive columns from).

Bean rows get one InMemoryBeanQueryContext per element class, built once (with any QueryableSettings bean applied) and cached for the lifetime of this converter instance, so QueryableSettings is read once per element class, not on every request. Map rows get one column per key of the first non-null row (type inferred from that row's value by the same rule as bean properties, see QueryProperty.searchTypeOf(Class): a Number → SearchType.NUMERIC, a Boolean → SearchType.BOOLEAN, an enum → SearchType.ENUM, a date/calendar/temporal → SearchType.TIMESTAMP, anything else (or a null) → SearchType.TEXT); this context is built on every request, since the key set can differ per response. Keys that appear only in later rows are not queryable.

&opts=counts=true adds TOTAL_HEADER / MATCHED_HEADER response headers carrying the session's total/matched row counts — each header is set only when the corresponding count is present. Without it, neither header is set. The response body itself stays a bare list either way.

Example:

@Rest(converters=Queryable.class) public class PeopleResource extends BasicRestServlet { @Bean public QueryableSettings queryableSettings() { return QueryableSettings.create().maxLimit(500).build(); } @RestGet("/people") public List<Person> getPeople() { return people; } }

GET /people?search=age=$gte(18)&sort=name,age:desc&view=name,age&position=20&limit=10

A bad column or option (e.g. ?sort=noSuchColumn) throws BeanQuerySyntaxException, which RestContext.convertThrowable maps to an HTTP 400 carrying an X-BeanQuery-Error header and, with problem details on, a "code" member.

GET /people?search=age=$gte(18)&opts=counts=true adds count headers to the (still bare-list) body:

X-BeanQuery-Total: 42 X-BeanQuery-Matched: 7

See Also:
Since:
10.0.0