You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by bu...@apache.org on 2018/04/04 15:56:43 UTC

svn commit: r1027845 - in /websites/production/cxf/content: cache/docs.pageCache docs/jax-rs-search.html

Author: buildbot
Date: Wed Apr  4 15:56:43 2018
New Revision: 1027845

Log:
Production update by buildbot for cxf

Modified:
    websites/production/cxf/content/cache/docs.pageCache
    websites/production/cxf/content/docs/jax-rs-search.html

Modified: websites/production/cxf/content/cache/docs.pageCache
==============================================================================
Binary files - no diff available.

Modified: websites/production/cxf/content/docs/jax-rs-search.html
==============================================================================
--- websites/production/cxf/content/docs/jax-rs-search.html (original)
+++ websites/production/cxf/content/docs/jax-rs-search.html Wed Apr  4 15:56:43 2018
@@ -32,8 +32,8 @@
 <link type="text/css" rel="stylesheet" href="/resources/highlighter/styles/shThemeCXF.css">
 
 <script src='/resources/highlighter/scripts/shCore.js'></script>
-<script src='/resources/highlighter/scripts/shBrushXml.js'></script>
 <script src='/resources/highlighter/scripts/shBrushJava.js'></script>
+<script src='/resources/highlighter/scripts/shBrushXml.js'></script>
 <script>
   SyntaxHighlighter.defaults['toolbar'] = false;
   SyntaxHighlighter.all();
@@ -118,11 +118,11 @@ Apache CXF -- JAX-RS Search
            <!-- Content -->
            <div class="wiki-content">
 <div id="ConfluenceContent"><h1 id="JAX-RSSearch-JAX-RSSearch">JAX-RS Search</h1><p>&#160;</p><p><style type="text/css">/*<![CDATA[*/
-div.rbtoc1508777326031 {padding: 0px;}
-div.rbtoc1508777326031 ul {list-style: disc;margin-left: 0px;}
-div.rbtoc1508777326031 li {margin-left: 0px;padding-left: 0px;}
+div.rbtoc1522857365130 {padding: 0px;}
+div.rbtoc1522857365130 ul {list-style: disc;margin-left: 0px;}
+div.rbtoc1522857365130 li {margin-left: 0px;padding-left: 0px;}
 
-/*]]>*/</style></p><div class="toc-macro rbtoc1508777326031">
+/*]]>*/</style></p><div class="toc-macro rbtoc1522857365130">
 <ul class="toc-indentation"><li><a shape="rect" href="#JAX-RSSearch-JAX-RSSearch">JAX-RS Search</a>
 <ul class="toc-indentation"><li><a shape="rect" href="#JAX-RSSearch-AdvancedSearchQueries">Advanced Search Queries</a></li><li><a shape="rect" href="#JAX-RSSearch-SupportedQueryLanguages">Supported Query Languages</a>
 <ul class="toc-indentation"><li><a shape="rect" href="#JAX-RSSearch-FeedItemQueryLanguage">Feed Item Query Language</a></li><li><a shape="rect" href="#JAX-RSSearch-OpenDataProtocol">Open Data Protocol</a></li></ul>
@@ -163,42 +163,42 @@ div.rbtoc1508777326031 li {margin-left:
 
 </pre>
 </div></div><p>Note that no "_s" or "_search" query parameter is available, the whole query string starting after "?" represents an actual FIQL expression.<br clear="none"> Please use "search.use.all.query.component" contextual property for this option be supported.</p><p>Alternatively the expressions can be encoded as URI path segments, see the sections below for more information.</p><h3 id="JAX-RSSearch-OpenDataProtocol">Open Data Protocol</h3><p>CXF 3.0.0-milestone2 supports the <a shape="rect" class="external-link" href="http://docs.oasis-open.org/odata/odata/v4.0/cos01/part2-url-conventions/odata-v4.0-cos01-part2-url-conventions.html#_Toc372793792" rel="nofollow">$filter</a> query defined as part of <a shape="rect" class="external-link" href="http://www.odata.org/" rel="nofollow">Open Data Protocol</a>, courtesy of <a shape="rect" class="external-link" href="http://olingo.incubator.apache.org/">Apache Olingo</a>.</p><p>The $filter query can have a number of the logical operator
 s, here is a summary of the operators supported in scope of Search API:</p><div class="table-wrap"><table class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" class="confluenceTh"><p>Operator</p></th><th colspan="1" rowspan="1" class="confluenceTh"><p>Description</p></th></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>"eq"</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>Equal</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>"ne"</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>Not Equal</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>"lt"</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>Less Than</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>"le"</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>Less or Equal</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>"gt"</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>Greater Than<
 /p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>"ge"</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>Greater or Equal</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>"and"</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>AND</p></td></tr><tr><td colspan="1" rowspan="1" class="confluenceTd"><p>"or"</p></td><td colspan="1" rowspan="1" class="confluenceTd"><p>OR</p></td></tr></tbody></table></div><p>&#160;</p><p>Please see the specification text for <a shape="rect" class="external-link" href="http://docs.oasis-open.org/odata/odata/v4.0/cos01/part2-url-conventions/odata-v4.0-cos01-part2-url-conventions.html#_Toc372793804" rel="nofollow">some examples</a>.</p><p>Please note that OData protocol is not supported by CXF Search API, only the $filter query is supported (only logical operators for now) for querying the application data with CXF Search API. Users should work directly with <a shape="rect" class="external-link" href
 ="http://olingo.incubator.apache.org/">Apache Olingo</a> to get the <a shape="rect" class="external-link" href="http://www.odata.org/" rel="nofollow">OData</a> protocol supported as part of the application flow.</p><p>Some of the following examples on this page may often refer to FIQL due to the fact FIQL has been supported for a long time, but the same examples will work with OData $filter expressions. For example, replace the "_s=name==CXF" query with "$filter=name eq CXF".</p><h2 id="JAX-RSSearch-Whentouseadvancedqueries.">When to use advanced queries.</h2><p>Consider a typical query expression such as "a=avalue&amp;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.</p><p>It is also to capture conditional expressi
 ons 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.</p><p>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).</p><p>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.</p><h2 id="JAX-RSSearch-DependenciesandConfiguration">Dependencies and Configuration</h2><p>The following dependency is required starting from CXF 2.6.0:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">   &lt;dependency&gt;
-      &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
-      &lt;artifactId&gt;cxf-rt-rs-extension-search&lt;/artifactId&gt;
-      &lt;version&gt;2.6.0&lt;/version&gt;
-   &lt;/dependency&gt;
-
-   &lt;!-- If working with OData --&gt;
-   &lt;!--
-       &lt;dependency&gt;
-            &lt;groupId&gt;org.apache.olingo&lt;/groupId&gt;
-            &lt;artifactId&gt;olingo-odata2-core-incubating&lt;/artifactId&gt;
-            &lt;version&gt;1.1.0&lt;/version&gt; 
-        &lt;/dependency&gt;
-   --&gt;
-&#160;</pre>
-</div></div><p>Additionally, starting from CXF 2.6.0, <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/cxf/trunk/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchContextProvider.java">SearchContextProvider</a> needs to be registered as jaxrs:provider.</p><h2 id="JAX-RSSearch-Workingwiththequeries">Working with the queries</h2><p><a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/cxf/trunk/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchContext.java">SearchContext</a> needs be injected into an application code and used to retrieve a <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/cxf/trunk/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchCondition.java">SearchCondition</a> representing the current FIQL/OData query. This SearchCondition can be used in a number of ways for finding the matching data.</p><p>In this section we as
 sume that the data to be matched are already available in memory. The follow-up section on converting the queries will show how the queries can be converted to some other query language typed or text expression.</p><p>So, suppose a list or map of Book instances is available. Here is one possible approach:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">&lt;dependency&gt;
+    &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
+    &lt;artifactId&gt;cxf-rt-rs-extension-search&lt;/artifactId&gt;
+    &lt;version&gt;2.6.0&lt;/version&gt;
+&lt;/dependency&gt;
+
+&lt;!-- If working with OData --&gt;
+&lt;!--
+&lt;dependency&gt;
+    &lt;groupId&gt;org.apache.olingo&lt;/groupId&gt;
+    &lt;artifactId&gt;olingo-odata2-core-incubating&lt;/artifactId&gt;
+    &lt;version&gt;1.1.0&lt;/version&gt; 
+&lt;/dependency&gt;
+--&gt;
+</pre>
+</div></div><p>Additionally, starting from CXF 2.6.0, <a shape="rect" class="external-link" href="https://github.com/apache/cxf/blob/master/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchContextProvider.java" rel="nofollow">SearchContextProvider</a> needs to be registered as jaxrs:provider.</p><h2 id="JAX-RSSearch-Workingwiththequeries">Working with the queries</h2><p><a shape="rect" class="external-link" href="https://github.com/apache/cxf/blob/master/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchContext.java" rel="nofollow">SearchContext</a> needs be injected into an application code and used to retrieve a <a shape="rect" class="external-link" href="https://github.com/apache/cxf/blob/master/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchCondition.java" rel="nofollow">SearchCondition</a> representing the current FIQL/OData query. This SearchCondition can be used in a number of ways for finding t
 he matching data.</p><p>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 the queries can be converted to some other query language typed or text expression.</p><p>So, suppose a list or map of Book instances is available. Here is one possible approach:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@Path("books")
 public class Books {
 
-private Map&lt;Long, Book&gt; books;
-@Context
-private SearchContext context;
-
- @GET
- public List&lt;Book&gt; getBook() {
-
-   SearchCondition&lt;Book&gt; sc = searchContext.getCondition(Book.class);
-   // SearchCondition#isMet method can also be used to build a list of matching beans
-
-   // iterate over all the values in the books map and return a collection of matching beans
-   List&lt;Book&gt; found = sc.findAll(books.values());
-   return found;
- }
+    private Map&lt;Long, Book&gt; books;
+    @Context
+    private SearchContext context;
+
+    @GET
+    public List&lt;Book&gt; getBook() {
+
+        SearchCondition&lt;Book&gt; sc = searchContext.getCondition(Book.class);
+        // SearchCondition#isMet method can also be used to build a list of matching beans
+
+        // iterate over all the values in the books map and return a collection of matching beans
+        List&lt;Book&gt; found = sc.findAll(books.values());
+        return found;
+    }
 }
 </pre>
-</div></div><p>Note that a searchContext.getCondition(Book.class) call may return an arbitrary complex SearchCondition, it can be a simple primitive<br clear="none"> expression or a more complex, composite one.</p><h2 id="JAX-RSSearch-Capturingthequeries">Capturing the queries</h2><p>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.</p><p>Note that by default, a bean such as Book class needs to have a matching property per every property name found in the FIQL expression, for example, given a 'name==b;id==123' expression, the Book class would need to have 'name' and 'id' properties available. The reason for this strict mode being enabled by default is that ignoring a property which can not be captured may lead to a false or unexpected match, for example, if Book 'name' property h
 as been renamed to 'title' then ignoring the 'name' property will lead to a wider match. Thus, if the property does not exist, org.apache.cxf.jaxrs.ext.search.PropertyNotFoundException will be thrown; capturing it can let returning an empty response or retry with the more lax mode, see the next paragraph.</p><p>When a more lax parsing of FIQL expressions is expected, for example, where the primitive expressions are joined by "OR", using SearchBean (see one of the next subsections) or setting a contextual property "search.lax.property.match" will help. The former option is better when you need to know the list of all the properties which have been used in the expression, even those which will not be possible to use for the actual search; the latter option will simply have the unrecognized properties ignored.</p><p>Note that a "search.decode.values" property can be used to have the 'reserved' characters such as FIQL ',' or ';' characters passed as percent-encoded characters as part of
  the search property values.</p><h3 id="JAX-RSSearch-Mappingofquerypropertiestobeanproperties">Mapping of query properties to bean properties</h3><p>As noted above, when a 'typed' bean such as Book.class is used to capture the expressions, a property found in the query expression that can not be mapped to a specific Book property will lead to an exception being reported or it can be optionally ignored. In the reality, there is a number of reasons why the direct match between properties found in query expressions and in capturing beans may not be ideal:</p><ul class="alternate"><li>Capturing beans may evolve independently of the actual queries; for example, a working query such as "name==b" will break if a Book 'name' gets renamed to 'title' which will make it difficult to have the queries bookmarked.</li><li>Direct match will simply not work for cases where an actual bean property does not belong to the capturing bean itself but to one of its child properties; for example, a JPA2 Bo
 ok entity may have an OwnerInfo bean with Name bean property which does contain a primitive 'name' property.</li></ul><p>The preferred approach, when working with typed beans, is to register a bean properties map, using a "search.bean.property.map" contextual property or directly with SearchContext. For example, given</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>Note that a searchContext.getCondition(Book. class) call may return an arbitrary complex SearchCondition, it can be a simple primitiveexpression or a more complex, composite one.</p><h2 id="JAX-RSSearch-Capturingthequeries">Capturing the queries</h2><p>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.</p><p>Note that by default, a bean such as Book class needs to have a matching property per every property name found in the FIQL expression, for example, given a 'name==b;id==123' expression, the Book class would need to have 'name' and 'id' properties available. The reason for this strict mode being enabled by default is that ignoring a property which can not be captured may lead to a false or unexpected match, for example, if Book 'name' property has been renamed t
 o 'title' then ignoring the 'name' property will lead to a wider match. Thus, if the property does not exist, org.apache.cxf.jaxrs.ext.search.PropertyNotFoundException will be thrown; capturing it can let returning an empty response or retry with the more lax mode, see the next paragraph.</p><p>When a more lax parsing of FIQL expressions is expected, for example, where the primitive expressions are joined by "OR", using SearchBean (see one of the next subsections) or setting a contextual property "search.lax.property.match" will help. The former option is better when you need to know the list of all the properties which have been used in the expression, even those which will not be possible to use for the actual search; the latter option will simply have the unrecognized properties ignored.</p><p>Note that a "search.decode.values" property can be used to have the 'reserved' characters such as FIQL ',' or ';' characters passed as percent-encoded characters as part of the search prope
 rty values.</p><h3 id="JAX-RSSearch-Mappingofquerypropertiestobeanproperties">Mapping of query properties to bean properties</h3><p>As noted above, when a 'typed' bean such as Book.class is used to capture the expressions, a property found in the query expression that can not be mapped to a specific Book property will lead to an exception being reported or it can be optionally ignored. In the reality, there is a number of reasons why the direct match between properties found in query expressions and in capturing beans may not be ideal:</p><ul class="alternate"><li>Capturing beans may evolve independently of the actual queries; for example, a working query such as "name==b" will break if a Book 'name' gets renamed to 'title' which will make it difficult to have the queries bookmarked.</li><li>Direct match will simply not work for cases where an actual bean property does not belong to the capturing bean itself but to one of its child properties; for example, a JPA2 Book entity may hav
 e an OwnerInfo bean with Name bean property which does contain a primitive 'name' property.</li></ul><p>The preferred approach, when working with typed beans, is to register a bean properties map, using a "search.bean.property.map" contextual property or directly with SearchContext. For example, given</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class Book {
 
     private int id;
@@ -220,7 +220,6 @@ public class Name {
     private String name;
     //setters and getters omitted for brevity
 }
-
 </pre>
 </div></div><p>and the following map:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">&lt;map&gt;
@@ -262,9 +261,9 @@ SQLPrinterVisitor&lt;SearchBean&gt; visi
 sc.accept(visitor);
 assertEquals("SELECT LEVEL_COLUMN FROM table 
               WHERE LEVEL_COLUMN &gt; '10'",
-              visitor.getResult());
+              visitor.getQuery());
 </pre>
-</div></div><h2 id="JAX-RSSearch-Convertingthequeries">Converting the queries</h2><p>SearchCondition can also be used to convert the search requirements (originally expressed in FIQL/OData) into other query languages. <br clear="none"> A custom <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/cxf/trunk/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchConditionVisitor.java">SearchConditionVisitor</a> 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.</p><h3 id="JAX-RSSearch-SQL">SQL</h3><p>org.apache.cxf.jaxrs.ext.search.sql.SQLPrinterVisitor can be used for creating SQL expressions. For example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><h2 id="JAX-RSSearch-Convertingthequeries">Converting the queries</h2><p>SearchCondition can also be used to convert the search requirements (originally expressed in FIQL/OData) into other query languages. <br clear="none"> A custom <a shape="rect" class="external-link" href="https://github.com/apache/cxf/blob/master/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchConditionVisitor.java" rel="nofollow">SearchConditionVisitor</a> 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.</p><h3 id="JAX-RSSearch-SQL">SQL</h3><p>org.apache.cxf.jaxrs.ext.search.sql.SQLPrinterVisitor can be used for creating SQL expressions. For example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">// ?_s="name==ami*;level=gt=10"
 SearchCondition&lt;Book&gt; sc = searchContext.getCondition(Book.class);
 SQLPrinterVisitor&lt;Book&gt; visitor = new SQLPrinterVisitor&lt;Book&gt;("table");
@@ -274,7 +273,7 @@ assertEquals("SELECT * FROM table
               name LIKE 'ami%' 
               AND 
               level &gt; '10'",
-              visitor.getResult());
+              visitor.getQuery());
 </pre>
 </div></div><p>Note that SQLPrinterVisitor can also be initialized with the names of columns and the field aliases map:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">// ?_s="level=gt=10"
@@ -287,7 +286,7 @@ SQLPrinterVisitor&lt;Book&gt; visitor =
 sc.accept(visitor);
 assertEquals("SELECT LEVEL_COLUMN FROM table 
               WHERE LEVEL_COLUMN &gt; '10'",
-              visitor.getResult());
+              visitor.getQuery());
 </pre>
 </div></div><p>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.</p><h3 id="JAX-RSSearch-JPA2.0">JPA 2.0</h3><p>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 <br clear="none"> javax.persistence.TypedQuery or javax.persistence.criteria.CriteriaQuery objects.</p><p>For example, given:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class Book {
@@ -319,8 +318,6 @@ public class Address {
     private String street;
     //setters and getters omitted for brevity
 }
-
-
 </pre>
 </div></div><p>the following code can be used:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">import javax.persistence.EntityManager;
@@ -385,18 +382,18 @@ for (Tuple tuple : tuples) {
 </pre>
 </div></div><p>Note that JPACriteriaQueryVisitor will automatically set aliases for an expression like "tuple.get('id', String.class)" to work.<br clear="none"> JPACriteriaQueryVisitor will be enhanced to support more of JPA2 advanced constructs in time.</p><p>Or, instead of using Tuple, use a capturing bean like BeanInfo:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public static class BookInfo {
-        private int id;
-        private String title;
+    private int id;
+    private String title;
 
-        public BookInfo() {
+    public BookInfo() {
             
-        }
+    }
         
-        public BookInfo(Integer id, String title) {
-            this.id = id;
-            this.title = title;
-        }
-        //setters and getters omitted for brevity
+    public BookInfo(Integer id, String title) {
+        this.id = id;
+        this.title = title;
+    }
+    //setters and getters omitted for brevity
  }
 
 // actual application code:
@@ -417,7 +414,6 @@ TypedQuery&lt;BookInfo&gt; query = visit
 
 List&lt;BookInfo&gt; bookInfo = typedQuery.getResultList();
 return bookInfo;
-
 </pre>
 </div></div><p>JPA2 typed converters also support join operations in cases when explicit collections are used, for example, given:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">@Entity(name = "Book")
@@ -484,7 +480,6 @@ public class BookReview {
         BAD
     }
 }
-
 </pre>
 </div></div><p>the following will find "all the books with good reviews written by Ted":</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">SearchCondition&lt;Book&gt; filter = new FiqlParser&lt;Book&gt;(Book.class).parse("reviews.review==good;reviews.authors==Ted");
@@ -495,7 +490,6 @@ SearchConditionVisitor&lt;Book, TypedQue
 filter.accept(jpa);
 TypedQuery&lt;Book&gt; query = jpa.getQuery();
 return query.getResultList();
-
 </pre>
 </div></div><p>org.apache.cxf.jaxrs.ext.search.jpa.JPALanguageVisitor for converting FIQL/OData expressions into JPQL expressions have also been introduced.</p><h4 id="JAX-RSSearch-Countexpressions">Count expressions</h4><p>Count expressions are supported at the two levels,</p><p>First, one may want to get the count of records matching a given search expression, this actually can be done by checking the size of the result list:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">TypedQuery&lt;Book&gt; query = jpa.getQuery();
@@ -507,7 +501,6 @@ return query.getResultList().size();
 JPACriteriaQueryVisitor&lt;Book, Long&gt; jpa = new JPACriteriaQueryVisitor&lt;Book, Long&gt;(em, Book.class, Long.class);
 filter.accept(jpa);
 long count = jpa.count();
-
 </pre>
 </div></div><p>&#160;</p><p>Second, <strong>only when using FIQL</strong>, 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'.<br clear="none"> 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"</p><h3 id="JAX-RSSearch-Lucene">Lucene</h3><p>Mapping of FIQL/OData expressions to Lucene (4.0.0-BETA) Query is supported starting from CXF 2.7.1. Please notice that starting from CXF 3.0.2, the Lucene version has been upgraded to 4.9.0 in order to benefit from query builders and other improvements.</p><p>org.apache.cxf.jaxrs.ext.search.lucene.LuceneQueryVisitor can be used to support the default (content) field or specific custom field queries.<br clear="none"> Queries for specific terms and phrases are supported.</p><p>Example, "find the documents conta
 ining a 'text' term":</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">import org.apache.lucene.search.Query;
@@ -553,15 +546,14 @@ LdapQueryVisitor&lt;Condition&gt; visito
 
 filter.accept(visitor.visitor());
 String ldap = visitor.getQuery();
-
 </pre>
 </div></div><h3 id="JAX-RSSearch-HBase">HBase</h3><p>&#160;</p><p>CXF 3.0.2 introduces an initial support for querying HBase databases. Please see <a shape="rect" class="external-link" href="https://fisheye6.atlassian.com/browse/cxf/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/hbase/HBaseVisitorTest.java?r=35b9209c04154bb00f1168cbeaa94314af070609" rel="nofollow">this test</a> for more information.</p><h3 id="JAX-RSSearch-Customvisitors">Custom visitors</h3><p>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.</p><h4 id="JAX-RSSearch-Untypedconverters">Untyped converters</h4><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class CustomSQLVisitor&lt;T&gt; extends AbstractSearchConditionVisitor&lt;T, String&gt; {
 
-private String tableName;
-private StringBuilder sb = new StringBuilder();
+    private String tableName;
+    private StringBuilder sb = new StringBuilder();
 
-public void visit(SearchCondition&lt;T&gt; sc) {
+    public void visit(SearchCondition&lt;T&gt; sc) {
         
         if (sb == null) {
             sb = new StringBuilder();
@@ -595,9 +587,9 @@ public void visit(SearchCondition&lt;T&g
 </div></div><h4 id="JAX-RSSearch-Typedconverters">Typed converters</h4><p>import org.custom.search.Query;</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">public class CustomTypedVisitor&lt;T&gt; extends AbstractSearchConditionVisitor&lt;T, Query&gt; {
 
-private Stack&lt;List&lt;Query&gt;&gt; queryStack = new Stack&lt;List&lt;Query&gt;&gt;();
+    private Stack&lt;List&lt;Query&gt;&gt; queryStack = new Stack&lt;List&lt;Query&gt;&gt;();
 
-public void visit(SearchCondition&lt;T&gt; sc) {
+    public void visit(SearchCondition&lt;T&gt; sc) {
                 
         PrimitiveStatement statement = sc.getStatement();
         if (statement != null) {
@@ -623,7 +615,7 @@ public void visit(SearchCondition&lt;T&g
         }
     }
 
-    public Query getResult() {
+    public Query getQuery() {
         return queryStack.peek().get(0);
     }
 }
@@ -643,9 +635,8 @@ public class SearchEngine {
         // note that the original search expression can also be retrieved 
         // using a SearchContext.getSearchExpression() method
 }
-
 </pre>
-</div></div><h2 id="JAX-RSSearch-ConvertingthequerieswithQueryContext">Converting the queries with QueryContext</h2><p><a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/cxf/trunk/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/QueryContext.java">QueryContext</a> is the helper context available from CXF 2.7.1 which makes it simpler for the application code to<br clear="none"> get the converted query expression, with the actual converter/visitor registered as the jaxrs contextual property, for example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><h2 id="JAX-RSSearch-ConvertingthequerieswithQueryContext">Converting the queries with QueryContext</h2><p><a shape="rect" class="external-link" href="https://github.com/apache/cxf/blob/master/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/QueryContext.javahe/cxf/jaxrs/ext/search/QueryContext.java" rel="nofollow">QueryContext</a> is the helper context available from CXF 2.7.1 which makes it simpler for the application code to<br clear="none"> get the converted query expression, with the actual converter/visitor registered as the jaxrs contextual property, for example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">import java.util.ArrayList;
 import java.util.List;
 import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
@@ -666,7 +657,6 @@ SQLPrinterVisitor&lt;SearchBean&gt; sqlV
 sqlVisitor.setVisitorState(new SBThrealLocalVisitorState());
 sf.getProperties(true).put("search.visitor", sqlVisitor);
 
-
 sf.setResourceClasses(BookStore.class);
 server = sf.create();
 </pre>
@@ -698,7 +688,6 @@ assertEquals("(a==a1,a==a2)", exp);
 // GET /search?a=a1&amp;b=b1
 exp = searchContext.getSearchExpression();
 assertEquals("(a==a1;b==b1)", exp);
-
 </pre>
 </div></div><p>Also, by default, if a query property name ends with "From" then "=ge=" (greater or equals to) will be used, and if ends with "Till" then "=lt=" will be used, for example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">// GET /search?ageFrom=10&amp;ageTill=20
@@ -861,7 +850,7 @@ public class BooksResource {
 
 }
 </pre>
-</div></div><p>Note this code assumes that "bookId" is mapped to "Book.id" property with the help of the contextual "search.bean.property.map" property as explained earlier.</p><h2 id="JAX-RSSearch-Validation">Validation</h2><p>First option is to have a bean capturing specific property values do a domain specific validation. For example, a Book.class may have its setName(String name) method validating the name value. <br clear="none"> Another option is to inject a custom <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/cxf/trunk/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/visitor/PropertyValidator.java">validator</a> into a visitor which is used to build the untyped or typed query.</p><p>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 t
 o be related to Books.</p><p>Bean Validation 1.1 can also be used.</p><h2 id="JAX-RSSearch-Buildingthequeries">Building the queries</h2><h3 id="JAX-RSSearch-FIQL">FIQL</h3><p>CXF 2.4.0 introduces <a shape="rect" class="external-link" href="http://svn.apache.org/repos/asf/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/search/client/SearchConditionBuilder.java">SearchConditionBuilder</a> which makes it simpler to build FIQL queries. SearchConditionBuilder is an abstract class that returns a FIQL builder by default:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>Note this code assumes that "bookId" is mapped to "Book.id" property with the help of the contextual "search.bean.property.map" property as explained earlier.</p><h2 id="JAX-RSSearch-Validation">Validation</h2><p>First option is to have a bean capturing specific property values do a domain specific validation. For example, a Book.class may have its setName(String name) method validating the name value. <br clear="none"> Another option is to inject a custom <a shape="rect" class="external-link" href="https://github.com/apache/cxf/blob/master/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/visitor/PropertyValidator.java" rel="nofollow">validator</a> into a visitor which is used to build the untyped or typed query.</p><p>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 t
 he ones known to be related to Books.</p><p>Bean Validation 1.1 can also be used.</p><h2 id="JAX-RSSearch-Buildingthequeries">Building the queries</h2><h3 id="JAX-RSSearch-FIQL">FIQL</h3><p>CXF 2.4.0 introduces <a shape="rect" class="external-link" href="https://github.com/apache/cxf/blob/master/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/client/SearchConditionBuilder.java" rel="nofollow">SearchConditionBuilder</a> which makes it simpler to build FIQL queries. SearchConditionBuilder is an abstract class that returns a FIQL builder by default:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">SearchConditionBuilder b = SearchConditionBuilder.instance();
 String fiqlQuery = b.is("id").greaterThan(123).query();
 
@@ -908,8 +897,6 @@ assertEquals("(foo==20,foo==10);bar=lt=1
 
 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);
-
-
 </pre>
 </div></div><p>&#160;</p><h2 id="JAX-RSSearch-Usingdatesinqueries">Using dates in queries</h2><p>By default, the date values have to have the following <a shape="rect" class="external-link" href="http://download.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html" rel="nofollow">format</a>: "yyyy-MM-dd", for example:</p><div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
 <pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">?_search=date=le=2010-03-11