JAX-RS Search
Table of Contents |
---|
Advanced Search Queries
...
Operator | Description |
---|---|
"eq" | Equal |
"ne" | Not Equal |
"lt" | Less Than |
"le" | Less or Equal |
"gt" | Greater Than |
"ge" | Greater or Equal |
"and" | AND |
"or" | OR |
...
Please see the specification text for some examples.
...
The fields map can help hide the names of the actual table columns/record fields from the Web frontend. Example, the users will know that the 'level' property is available while internally it will be converted to a LEVEL_COLUMN name.
Warning: Using the SQLPrinterVisitor may leave your service open to SQL injection attacks. Please take appropriate steps to avoid these attacks (for example validating queries using a custom PropertyValidator, or manually escaping the input values).
JPA 2.0
CXF 2.6.4 and CXF 2.7.1 introduce org.apache.cxf.jaxrs.ext.search.jpa.JPATypedQueryVisitor and org.apache.cxf.jaxrs.ext.search.jpa.JPACriteriaQueryVisitor which can be used to capture FIQL/OData expressions into
javax.persistence.TypedQuery or javax.persistence.criteria.CriteriaQuery objects.
...
Code Block | ||||
---|---|---|---|---|
| ||||
SearchCondition<Book> filter = new FiqlParser<Book>(Book.class).parse("reviews.review==good;reviews.authors==Ted"); JPACriteriaQueryVisitor<Book, Long> jpa = new JPACriteriaQueryVisitor<Book, Long>(em, Book.class, Long.class); filter.accept(jpa); long count = jpa.count(); |
Second, only when using FIQL, a count extension can be used. For example, one may want to find 'all the books written by at least two authors or all the books with no reviews'.
If a collection entity such as BookReview has a non primitive type, then typing "reviews==0" is all what is needed, otherwise a count extension needs to be used, for example: "count(authors)=ge=2"
...
Code Block | ||||
---|---|---|---|---|
| ||||
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_4_9); // Lower-case filter and stop-words filter are part of the StandardAnalyzer SearchCondition<SearchBean> filter = new FiqlParser<SearchBean>(SearchBean.class).parse("contents==pears and APPLES"); LuceneQueryVisitor<SearchBean> lucene = new LuceneQueryVisitor<SearchBean>("contents", analyzer); lucene.visit(filter); org.apache.lucene.search.Query query = lucene.getQuery(); |
LDAP
Mapping of FIQL/OData expressions to LDAP queries as defined by RFC-4515 is supported starting from CXF 2.7.1 with the help of org.apache.cxf.jaxrs.ext.search.ldap.LdapQueryVisitor. Use this visitor when working with LDAP or OSGI.
...
Note that since CXF 3.2.5 the query values are encoded by default, to prevent possible LDAP injection attacks. If you want to support wildcard searching with the LdapQueryVisitor from CXF 3.2.5 onwards, it is necessary to set the 'encodeQueryValues' property of LdapQueryVisitor to 'false'.
HBase
CXF 3.0.2 introduces an initial support for querying HBase databases. Please see this test for more information.
Custom visitors
In cases when a custom conversion has to be done, a converter for doing the untyped (example, SQL) or typed (example, JPA2 TypedQuery) conversions can be provided.
...
Code Block | ||||
---|---|---|---|---|
| ||||
@Path("/")
public class BookStore {
@GET
@Path("/books/{expression}")
@Produces("application/xml")
public List<Book> getBookQueryContext(@PathParam("expression") String expression,
@Context QueryContext searchContext)
throws BookNotFoundFault {
String sqlExpression = searchContext.getConvertedExpression(expression, Book.class);
// pass it to the SQL DB and return the list of Books
}
}
|
...
Code Block | ||||
---|---|---|---|---|
| ||||
// 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); |
Using dates in queries
By default, the date values have to have the following format: "yyyy-MM-dd", for example:
...
Code Block | ||||
---|---|---|---|---|
| ||||
Map<String, String> props = new HashMap<String, String>(); props.put("search.date-format", "yyyy-MM-dd'T'HH:mm:ss"); props.put("search.timezone.support", "false"); Date d = df.parse("2011-03-01 12:34:00"); FiqlSearchConditionBuilder bCustom = new FiqlSearchConditionBuilder(props); String ret = bCustom.is("foo").equalTo(d).query(); assertEquals("foo==2011-03-01T12:34:00", ret); |
...
Relative dates
Date value can be specified as a duration from the current date/time, as its string representation, "PnYnMnDTnHnMnS".
Resulted date will be calculated as a current date + specified duration. For example:
Code Block | ||||
---|---|---|---|---|
| ||||
?_search=date=ge=-P90D |
This query will search for a date which is 90 days in the past or newer.
...
Custom org.apache.cxf.jaxrs.ext.search.SearchConditionParser implementations can be registered as a "search.parser" contextual property starting from CXF 3.0.0-milestone2.
OData
Please use a "search.query.parameter.name" contextual property to indicate to the runtime that an OData '$filter' query option needs to be checked for the query expression and a "search.parser" property to point to the instance of org.apache.cxf.jaxrs.ext.search.odata.ODataParser, as shown in this test, see the startServers function.
...
Code Block | ||||
---|---|---|---|---|
| ||||
<cxf:bus> <cxf:properties> <entry key="search.query.parameter.name" value="$filter" /> <entry key="search.parser"> <bean class="org.apache.cxf.jaxrs.ext.search.odata.ODataParser"> <constructor-arg value="#{ T(org.apache.cxf.jaxrs.ext.search.SearchBean) }" /> </bean> </entry> </cxf:properties> </cxf:bus> |
Also note that Apache Olingo offers its own visitor model which can be used to work with JPA2, etc.
...
To demonstrate the full power of the CXF 3.0.2 content extraction and search capabiities, the demo project 'jax_rs_search' has been developed and is distributed in the samples bundle. The project could be found in the official Apache CXF Github repository. It integrates together Apache CXF, Apache Lucene and Apache Tika showing off some advanced features related to custom analyzers and different filter criteria (keyword and phrase search).
...