Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

JAX-RS Search

 

Table of Contents

FIQL search queries

Introduction

Advanced Search Queries

CXF supports mapping the advanced query expressions to the typed Search API with the help of query language specific parsers.   

Supported Query Languages

Feed Item Query Language

CXF JAXRS (since 2.3.0) supports Feed Item Query Language(FIQL) . FIQL provides for a way to express complex search expressions using an intuitive and URI friendly languageis supported since CXF 2.3..

For example, the following query

...

Alternatively the expressions can be encoded as URI path segments, see the sections below for more information.

Open Data Protocol

When to use

...

advanced queries.

Consider a typical query expression such as "a=avalue&c=cvalue". This can mean either "find all resources with 'a' and 'c' properties equal to 'avalue' and 'cvalue'" or "find all resources with 'a' or 'c' properties equal to 'avalue' and 'cvalue'". It is application specific on whether it is "and" or "or" as far as the combination of multiple query properties is concerned.

It is also to capture conditional expressions with the custom language, example, "find all resource with 'a' property less than 123" when a number of properties is large or the entities which can be searched are created dynamically.

Use FIQL or OData for capturing simple or medium complexity queries, typically in cases where a set of properties that a user can specify is well-known. Example, a book store resource will let users search books given a number of useful properties(those of Book and/or Library a given book is available in, etc).

Furthermore, consider using FIQL/OData and SearchConditionVisitor for the purpose of generalizing the search code, when the number of properties and entities is large, dynamic, etc.

...

Additionally, in CXF 2.6.0, SearchContextProvider needs to be registered as jaxrs:provider.

Working with

...

the queries

To work with FIQL queries, a SearchContext needs be injected into an application code and used to retrieve a SearchCondition representing the current FIQL/OData query. This SearchCondition can be used in a number of ways for finding the matching data.

In this section we assume that the data to be matched are already available in memory. The follow-up section on converting the queries will show how FIQL the queries can be converted to some other query language typed or text expression.

...

Note that a searchContext.getCondition(Book.class) call may return an arbitrary complex SearchCondition, it can be a simple primitive
expression or a more complex, composite one.

Capturing

...

the queries

For the query expression to be captured, a bean like Book.class is instantiated and has all the search properties injected into it. A complex composite expression will be 'injected' into a number of Book instances - something that may have to be optimized.

...

Code Block
java
java
// ?_s="level=gt=10"
SearchCondition<SearchBean> sc = searchContext.getCondition(SearchBean.class);

Map\<, String\> fieldMap = new HashMap\<String, String\>();
fieldMap.put("level", "LEVEL_COLUMN");

SQLPrinterVisitor<SearchBean> visitor = new SQLPrinterVisitor<SearchBean>(fieldMap, "table", "LEVEL_COLUMN");
sc.accept(visitor);
assertEquals("SELECT LEVEL_COLUMN FROM table 
              WHERE LEVEL_COLUMN > '10'",
              visitor.getResult());

Converting

...

the queries

SearchCondition can also be used to convert the search requirements (originally expressed in FIQL) into other query languages.
A custom SearchConditionVisitor implementation can be used to convert SearchCondition objects into custom expressions or typed objects. CXF ships visitors for converting expressions to SQL, JPA 2.0 CriteriaQuery or TypedQuery, Lucene Query.

...

Code Block
java
java
@Path("/search")
public class SearchEngine {
    @Context
    private UriInfo ui;

    @GET
    public List<Book> findBooks() {
        MultivaluedMap<String, String> params = ui.getQueryParameters();
        String fiqlQuery = params.getFirst("_s");
        // delegate to your own custom handler 

        // note that the original search expression can also be retrieved 
        // using a SearchContext.getSearchExpression() method
}

Converting

...

the queries with QueryContext

QueryContext is the helper context available from CXF 2.7.1 which makes it simpler for the application code to
get the converted query expression, with the actual converter/visitor registered as the jaxrs contextual property, for example:

...

Finally, avoid letting users to use properties whose values which can not be well validated in the application code. Using a typed capturing bean like Book.class offers a perfect option to limit a number of supported properties to the ones known to be related to Books.

Building the queries

FIQL

...

CXF 2.4.0 introduces SearchConditionBuilder which makes it simpler to build FIQL queries. SearchConditionBuilder is an abstract class that returns a FIQL builder by default:

...

Code Block
java
java
// Connecting composite or() and and() expressions will add "()" implicitly:
String ret = b.is("foo").equalTo(20, 10).and("bar").lessThan(10).query();
assertEquals("(foo==20,foo==10);bar=lt=10", ret);

// wrap() method can be used to wrap explicitly:

String ret = b.is("foo").equalTo(10).and("bar").lessThan(10).wrap().or("bar").greaterThan(25).query();
assertEquals("(foo==20;bar=lt=10),bar=gt=25", ret);


OData

Using dates in queries

By default, the date values have to have the following format: "yyyy-MM-dd", for example:

...