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 Sep 13 15:05:52 
2017
@@ -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/shBrushJava.js'></script>
 <script src='/resources/highlighter/scripts/shBrushXml.js'></script>
+<script src='/resources/highlighter/scripts/shBrushJava.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.rbtoc1505311241756 {padding: 0px;}
-div.rbtoc1505311241756 ul {list-style: disc;margin-left: 0px;}
-div.rbtoc1505311241756 li {margin-left: 0px;padding-left: 0px;}
+div.rbtoc1505314890260 {padding: 0px;}
+div.rbtoc1505314890260 ul {list-style: disc;margin-left: 0px;}
+div.rbtoc1505314890260 li {margin-left: 0px;padding-left: 0px;}
 
-/*]]>*/</style></p><div class="toc-macro rbtoc1505311241756">
+/*]]>*/</style></p><div class="toc-macro rbtoc1505314890260">
 <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>
@@ -147,10 +147,10 @@ div.rbtoc1505311241756 li {margin-left:
 </li></ul>
 </li></ul>
 </div><h2 id="JAX-RSSearch-AdvancedSearchQueries">Advanced Search 
Queries</h2><p>CXF supports mapping the advanced query expressions to the typed 
Search API with the help of query language specific parsers.&#160; 
&#160;</p><h2 id="JAX-RSSearch-SupportedQueryLanguages">Supported Query 
Languages</h2><h3 id="JAX-RSSearch-FeedItemQueryLanguage">Feed Item Query 
Language</h3><p><a shape="rect" class="external-link" 
href="http://tools.ietf.org/html/draft-nottingham-atompub-fiql-00"; 
rel="nofollow">Feed Item Query Language</a>(FIQL) is supported since CXF 
2.3.0.</p><p>For example, the following query</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">?_s=name==CXF;version=ge=2.2
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">?_s=name==CXF;version=ge=2.2
 </pre>
 </div></div><p>lets users search for all the Apache projects with the name 
'CXF' and the version greater or equal to '2.2'. The initial '=' separates the 
name of the query '_s' from the FIQL expression, while '==' and '=ge=' convey 
'equals to' and 'greater or equals to' respectively.<br clear="none"> An 
expression such as "name==CXF*" can be used to do the partial equality check 
(example: the name should start from "CXF").</p><p>More complex composite 
expressions can also be expressed easily enough, examples:</p><div class="code 
panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// Find all employees younger than 25 or older than 35 
living in London
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// Find all employees younger than 25 or older than 35 
living in London
 /employees?_s=(age=lt=25,age=gt=35);city==London
 
 // Find all books on math or physics published in 1999 only.
@@ -158,12 +158,12 @@ div.rbtoc1505311241756 li {margin-left:
 
 </pre>
 </div></div><p>Here is a summary of FIQL operators:</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>"=="</p></td><td colspan="1" 
rowspan="1" class="confluenceTd"><p>Equal</p></td></tr><tr><td colspan="1" 
rowspan="1" class="confluenceTd"><p>"!="</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>";"</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>AND</p></td></tr><tr><td colspan="1" rowspan="1" 
class="confluenceTd"><p>","</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>OR</p></td></tr></tbody></table></div><p>The last two 
operators, ","(OR) and ";"(AND) are used to concatenate and build composite 
(possibly nested) expressions, while the first 6 operators are used to build so 
called primitive expressions.</p><p>From CXF 2.7.7: single '=' operator can be 
optionally supported instead of '==': set a 
"fiql.support.single.equals.operator" contextual property to "true".</p><p>As 
you can see FIQL is rich enough for the service implementations to offer a more 
interesting search experience around the well-known data, while still keeping 
the complexity of U
 RI expressions under control which makes it simpler to share such URI queries 
as well as use the same query language no matter what data store is used 
internally by the service.</p><p>Note, when passing the FIQL queries via URI 
query parameters, either '_search' or '_s' query parameter has to be used to 
mark a FIQL expression for it not to 'interfere' with other optional query 
parameters. Starting from CXF 2.7.2 it is also possible to use the whole query 
component to convey a FIQL expression, example,</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// Find all books on math or physics published in 1999 
only.
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// Find all books on math or physics published in 1999 
only.
 /books?date=lt=2000-01-01;date=gt=1999-01-01;(sub==math,sub==physics)
 
 </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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">   &lt;dependency&gt;
+<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;
@@ -179,7 +179,7 @@ div.rbtoc1505311241756 li {margin-left:
    --&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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">@Path("books")
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">@Path("books")
 public class Books {
 
 private Map&lt;Long, Book&gt; books;
@@ -199,7 +199,7 @@ private SearchContext context;
 }
 </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">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">public class Book {
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">public class Book {
 
     private int id;
     private OwnerInfo ownerinfo;
@@ -223,17 +223,17 @@ public class Name {
 
 </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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">&lt;map&gt;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">&lt;map&gt;
  &lt;!-- 'oname' is alias for the actual nested bean property --&gt;
  &lt;entry key="oname" value="ownerinfo.name.name"/&gt;
 &lt;/map&gt;
 </pre>
 </div></div><p>will let users type and bookmark queries (and without seeing 
them producing unexpected results) like this one:</p><div class="code panel 
pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">//Find all the books owned by Fred with id greater than 
100
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">//Find all the books owned by Fred with id greater than 
100
 /books?_s=id=gt=100;oname=Fred
 </pre>
 </div></div><p>Note, a property name such as "ownerinfo.name.name" uses '.' to 
let the parser navigate to the actual Name bean which has a 'name' property. 
This can be optimized in cases where the owner bean is known to have either a 
constructor or static valueOf() method accepting the 'name' property, for 
example, given</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">public class Name {
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">public class Name {
 
     private String name;
     public Name() {
@@ -245,14 +245,14 @@ public class Name {
 }
 </pre>
 </div></div><p>the mapping between "oname" and "ownerinfo.name" will work 
too.</p><p>You can also have many to one mappings, for example</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">&lt;map&gt;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">&lt;map&gt;
  &lt;!-- 'oname' and 'owner' are aliases for the 'ownerinfo.name.name' bean 
property --&gt;
  &lt;entry key="oname" value="ownerinfo.name.name"/&gt;
  &lt;entry key="owner" value="ownerinfo.name.name"/&gt;
 &lt;/map&gt;
 </pre>
 </div></div><h3 id="JAX-RSSearch-Dealingwithmistypedpropertynames">Dealing 
with mistyped property names</h3><p>Consider a case where a documented search 
property is named as 'address' (lower case) and a query contains a mistyped 
'Address' instead. In this case, unless a&#160;"search.lax.property.match" 
property is set, PropertyNotFoundException will be thrown.</p><p>Supporting 
case-insensitive property mapping is easy, register a 
"search.bean.property.map" (mentioned earlier) map as Java TreeMap</p><p>with a 
case-insensitive String.CASE_INSENSITIVE_ORDER Comparator.</p><p>However it 
will not help if the 'address' property was mistyped as 'adress'. In this case, 
"search.bean.property.map" might still be useful with having few more keys 
supporting some typical typos, example, 'adress' - 'address',&#160;'addres' - 
'address', etc.</p><p>Starting from&#160; CXF 
3.1.5,&#160;org.apache.cxf.jaxrs.ext.search.PropertyNameConverter&#160; is 
available and might be used for a more sophisticated 
 conversion of mistyped property names to correct names.&#160;</p><p>The 
implementation can be registered as a "search.bean.property.converter" endpoint 
contextual property.</p><h3 id="JAX-RSSearch-Parserproperties">Parser 
properties</h3><p>The parser properties are the ones which tell the parser how 
to treat the conversion of Date values and the unrecognized search property 
names.</p><p>As explained above, "search.lax.property.match" can be used to 
tell the parser that it should ignore the search property names which have no 
corresponding bean properties.</p><p>"search.date.format" and 
"search.timezone.support" tell the parser how to convert the date values, see 
"Using dates in queries" section.</p><p>More properties may be supported in the 
future.</p><p>All of these properties can be set as endpoint contextual 
properties or directly with SearchContext.</p><h2 
id="JAX-RSSearch-Mappingofquerypropertiestocolumn/fieldnames">Mapping of query 
properties to column/field names</h2><p>When 
 converting FIQL queries to SQL or other untyped query language expressions, as 
well as when using Lucene converter, it can be useful to be able to map between 
an actual query parameter and the column or field name. All FIQL converters 
shipped with CXF have constructors accepting a map for mapping the queries to 
columns/fields. See the next "SearchBean" section for one example.</p><p>Note 
this property is not the same as the one described in the "Mapping of query 
properties to bean properties" section. The latter (the one described in the 
previous section) is required for getting FIQL queries captured into typed, 
domain specific beans like Book, and it can be sufficient for JPA2 which also 
has annotations like @Column.</p><h2 
id="JAX-RSSearch-SearchBean">SearchBean</h2><p>org.apache.cxf.jaxrs.ext.search.SearchBean
 is a utility bean class which can simplify analyzing the captured FIQL 
expressions and converting them to the other language expressions, in cases 
where having to update th
 e bean class such as Book.class with all the properties that may need to be 
supported is not practical or the properties need to be managed manually. For 
example:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// ?_s="level=gt=10"
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// ?_s="level=gt=10"
 SearchCondition&lt;SearchBean&gt; sc = 
searchContext.getCondition(SearchBean.class);
 
 Map\&lt;, String\&gt; fieldMap = new HashMap\&lt;String, String\&gt;();
@@ -265,7 +265,7 @@ assertEquals("SELECT LEVEL_COLUMN FROM t
               visitor.getResult());
 </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">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// ?_s="name==ami*;level=gt=10"
+<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");
 sc.accept(visitor);
@@ -277,7 +277,7 @@ assertEquals("SELECT * FROM table
               visitor.getResult());
 </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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// ?_s="level=gt=10"
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// ?_s="level=gt=10"
 SearchCondition&lt;Book&gt; sc = searchContext.getCondition(Book.class);
 
 Map&lt;String, String&gt; fieldMap = new HashMap&lt;String, String&gt;();
@@ -290,7 +290,7 @@ assertEquals("SELECT LEVEL_COLUMN FROM t
               visitor.getResult());
 </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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">public class Book {
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">public class Book {
 
     private String title;
     private Date date;
@@ -323,7 +323,7 @@ public class Address {
 
 </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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">import javax.persistence.EntityManager;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
 
 // init EntityManager as required
@@ -350,7 +350,7 @@ TypedQuery&lt;Book&gt; typedQuery = visi
 List&lt;Book&gt; books = typedQuery.getResultList();
 </pre>
 </div></div><p>Using CriteriaQuery is preferred in cases when the actual 
result has to be shaped into a bean of different type, using one of JPA2 
CriteriaBuilder's shape methods (array(), construct() or tuple()). For 
example:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// Find the books owned by Barry who lives in London, 
published starting from the first month of 2000 
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// Find the books owned by Barry who lives in London, 
published starting from the first month of 2000 
 // ?_s="date=ge=2000-01-01;ownername=barry;address=london"
 
 // this map will have to be set as a contextual property on the jaxrs endpoint
@@ -384,7 +384,7 @@ 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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">public static class BookInfo {
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">public static class BookInfo {
         private int id;
         private String title;
 
@@ -420,7 +420,7 @@ 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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">@Entity(name = "Book")
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">@Entity(name = "Book")
 public class Book {
 
     private List&lt;BookReview&gt; reviews = new 
LinkedList&lt;BookReview&gt;();
@@ -487,7 +487,7 @@ public class BookReview {
 
 </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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">SearchCondition&lt;Book&gt; filter = new 
FiqlParser&lt;Book&gt;(Book.class).parse("reviews.review==good;reviews.authors==Ted");
+<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");
 // in practice, map "reviews.review" to "review", "reviews.authors" to 
"reviewAuthor" 
 // and have a simple query like "review==good;reviewAuthor==Ted" instead
 
@@ -498,11 +498,11 @@ 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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">TypedQuery&lt;Book&gt; query = jpa.getQuery();
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">TypedQuery&lt;Book&gt; query = jpa.getQuery();
 return query.getResultList().size();
 </pre>
 </div></div><p>However this can be very inefficient for large number of 
records, so using a CriteriaBuilder count operation is recommended, for 
example:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">SearchCondition&lt;Book&gt; filter = new 
FiqlParser&lt;Book&gt;(Book.class).parse("reviews.review==good;reviews.authors==Ted");
+<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");
 
 JPACriteriaQueryVisitor&lt;Book, Long&gt; jpa = new 
JPACriteriaQueryVisitor&lt;Book, Long&gt;(em, Book.class, Long.class);
 filter.accept(jpa);
@@ -510,7 +510,7 @@ 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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">import org.apache.lucene.search.Query;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">import org.apache.lucene.search.Query;
 
 SearchCondition&lt;SearchBean&gt; filter = new 
FiqlParser&lt;SearchBean&gt;(SearchBean.class).parse("ct==text");
 LuceneQueryVisitor&lt;SearchBean&gt; lucene = new 
LuceneQueryVisitor&lt;SearchBean&gt;("ct", "contents");
@@ -519,14 +519,14 @@ org.apache.lucene.search.Query termQuery
 // use Query
 </pre>
 </div></div><p>Note, "new LuceneQueryVisitor&lt;SearchBean&gt;("ct", 
"contents");" is a simple constructor which lets create a mapping between the 
"ct" name used in the query and the actual default content field. It is not 
required to use this mapping but it is recommended as it keeps the query 
expression shorter and does not leak the actual internal Lucene field 
name.</p><p>All the FIQL operators have been mapped to related Lucene Query 
objects. Queries such as "Less than", or "Greater than and less than" will work 
fine against the typed fields like "org.apache.lucene.document.IntField". The 
visitor can be configured with a "primitiveFieldTypeMap" map property to help 
it map a given query name, example "id" to Integer.class.</p><p>Phrases are 
supported too. Suppose you have few documents with each of them containing name 
and value pairs like "name=Fred", "name=Barry" and you'd like to list only the 
documents containing "name=Fred":</p><div class="code panel pdl" 
style="border-width
 : 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">SearchCondition&lt;SearchBean&gt; filter = new 
FiqlParser&lt;SearchBean&gt;(SearchBean.class).parse("name==Fred");
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">SearchCondition&lt;SearchBean&gt; filter = new 
FiqlParser&lt;SearchBean&gt;(SearchBean.class).parse("name==Fred");
 LuceneQueryVisitor&lt;SearchBean&gt; lucene = new 
LuceneQueryVisitor&lt;SearchBean&gt;("contents");
 lucene.visit(filter);
 org.apache.lucene.search.Query phraseQuery = lucene.getQuery();
 // use query
 </pre>
 </div></div><p>In this example, the visitor is requested to create Lucene 
org.apache.lucene.search.PhraseQuery against the specified contents field 
("contents"). The visitor can also accept a contentsFieldMap map property when 
different phrases may need to be checked against different contents 
fields.</p><p>Starting from CXF 3.0.2, the typed Date range queries are 
supported by LuceneQueryVisitor. However, this feature should be used together 
with 'primitiveFieldTypeMap' in order to hint the visitor which fields are 
temporal and should be treated as such in the filter expressions. For 
example:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">Map&lt; String, Class&lt; ? &gt; &gt; fieldTypes = new 
LinkedHashMap&lt; String, Class&lt; ? &gt; &gt;();
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">Map&lt; String, Class&lt; ? &gt; &gt; fieldTypes = new 
LinkedHashMap&lt; String, Class&lt; ? &gt; &gt;();
 fieldTypes.put( "modified", Date.class);
 
 SearchCondition&lt;SearchBean&gt; filter = new 
FiqlParser&lt;SearchBean&gt;(SearchBean.class).parse("modified=gt=2007-09-16");
@@ -536,7 +536,7 @@ lucene.visit(filter);
 
 org.apache.lucene.search.Query query = lucene.getQuery();</pre>
 </div></div><p>LuceneQueryVisitor supports wide range of date formats, still 
providing the option to customize it using 'search.date-format' property. This 
property accepts the date/time pattern expression in the SimpleDateFormat 
format. Also, since CXF 3.0.2, the LuceneQueryVisitor&#160; could be configured 
to use the Lucene analyzer. The reason to use analyzer is that during Lucene 
query construction the visitor can use the per-field filters and tokenizers, 
taking into account stemming, stop-worlds, lower-casing, etc., as such properly 
processing the filter expression. For example:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">Analyzer analyzer = new 
StandardAnalyzer(Version.LUCENE_4_9);
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">Analyzer analyzer = new 
StandardAnalyzer(Version.LUCENE_4_9);
 
 // Lower-case filter and stop-words filter are part of the StandardAnalyzer
 SearchCondition&lt;SearchBean&gt; filter = new 
FiqlParser&lt;SearchBean&gt;(SearchBean.class).parse("contents==pears and 
APPLES");
@@ -545,7 +545,7 @@ lucene.visit(filter);
 
 org.apache.lucene.search.Query query = lucene.getQuery();</pre>
 </div></div><p>&#160;</p><h3 id="JAX-RSSearch-LDAP">LDAP</h3><p>Mapping of 
FIQL/OData expressions to LDAP queries as defined by <a shape="rect" 
class="external-link" href="http://tools.ietf.org/html/rfc4515"; 
rel="nofollow">RFC-4515</a> 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.</p><p>Here is a summary of LDAP filter 
operators:</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>"="</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>Equal</p></td></tr><tr><td colspan="1" rowspan="1" 
class="confluenceTd"><p>"!"</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 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 or Equal</p></td></tr><tr><td colspan="1" 
rowspan="1" class="confluenceTd"><p>"&amp;"</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>AND</p></td></tr><tr><td colspan="1" rowspan="1" 
class="confluenceTd"><p>"|"</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>OR</p></td></tr></tbody></table></div><p>FIQL "=le=" 
and "=lt=" will both map to "&lt;=", while "=ge=" and "=gt=" to 
"&gt;=".</p><p>For example:</p><div class="table-wrap"><table 
class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1" 
class="confluenceTh"><p>FIQL</p></th><th colspan="1" rowspan="1" 
class="confluenceTh"><p>LDAP</p></th></tr><tr><td colspan="1" rowspan="1" 
class="confluenceTd"><p>"name==bar*"</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>"(name=ba
 r*)"</p></td></tr><tr><td colspan="1" rowspan="1" 
class="confluenceTd"><p>"name!=bar"</p></td><td colspan="1" rowspan="1" 
class="confluenceTd"><p>"(!name=bar)"</p></td></tr><tr><td colspan="1" 
rowspan="1" class="confluenceTd"><p>"name!=bar;id=gt=10"</p></td><td 
colspan="1" rowspan="1" 
class="confluenceTd"><p>"(&amp;(!name=bar)(id&gt;=10))"</p></td></tr><tr><td 
colspan="1" rowspan="1" 
class="confluenceTd"><p>"name!=bar;(id=gt=10,id=lt=5)"</p></td><td colspan="1" 
rowspan="1" 
class="confluenceTd"><p>"(&amp;(!name=bar)(|(id&gt;=10)(id&lt;=5)))"</p></td></tr></tbody></table></div><p>The
 converter is created like all other converters:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// FIQL "oclass=Bar"
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// FIQL "oclass=Bar"
 
 // map 'oclass' used in the FIQL query to the actual property name, 
'objectClass'
 LdapQueryVisitor&lt;Condition&gt; visitor = 
@@ -556,7 +556,7 @@ 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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">public class CustomSQLVisitor&lt;T&gt; extends 
AbstractSearchConditionVisitor&lt;T, String&gt; {
+<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();
@@ -593,7 +593,7 @@ public void visit(SearchCondition&lt;T&g
 }
 </pre>
 </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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">public class CustomTypedVisitor&lt;T&gt; extends 
AbstractSearchConditionVisitor&lt;T, Query&gt; {
+<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;();
 
@@ -629,7 +629,7 @@ public void visit(SearchCondition&lt;T&g
 }
 </pre>
 </div></div><h4 id="JAX-RSSearch-Customparsing">Custom parsing</h4><p>If 
needed you can access a FIQL/OData query directly and delegate it further to 
your own custom FIQL handler:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">@Path("/search")
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">@Path("/search")
 public class SearchEngine {
     @Context
     private UriInfo ui;
@@ -646,7 +646,7 @@ public class SearchEngine {
 
 </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">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">import java.util.ArrayList;
+<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;
 import org.apache.cxf.jaxrs.ext.search.QueryContextProvider;
@@ -671,7 +671,7 @@ sf.setResourceClasses(BookStore.class);
 server = sf.create();
 </pre>
 </div></div><p>and convert the queries:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">@Path("/")
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">@Path("/")
 public class BookStore { 
     @GET
     @Path("/books/{expression}")
@@ -685,13 +685,13 @@ public class BookStore {
 }
 </pre>
 </div></div><p>where the client code may look like this:</p><div class="code 
panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">String address = 
"http://localhost:8080/bookstore/books/id=ge=123";;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">String address = 
"http://localhost:8080/bookstore/books/id=ge=123";;
 WebClient client = WebClient.create(address);
 client.accept("application/xml");
 List&lt;Book&gt; books = client.getCollection(Book.class);
 </pre>
 </div></div><p>Note, given that SQLPrinterVisitor will be shared between 
multiple requests it has to be made thread-safe by injecting a thread-local<br 
clear="none"> 
org.apache.cxf.jaxrs.ext.search.visitor.SBThrealLocalVisitorState. This is not 
required when the visitor is created in the code on the per-request 
basis.</p><p>Custom visitors which are expected to be singletons and have the 
state accumulating between multiple visit calls have to be thread safe. Utility 
org.apache.cxf.jaxrs.ext.search.visitor.ThrealLocalVisitorState class can be 
used.</p><h2 id="JAX-RSSearch-PlainqueriestoFIQLconversion">Plain queries to 
FIQL conversion</h2><p>If you'd like to generalize the processing of search 
queries and use FIQL visitors, you may want to consider setting up a contextual 
property "search.use.plain.queries" to "true" and get the plain query 
expressions converted to FIQL expressions internally.</p><div class="code panel 
pdl" style="border-width: 1px;"><div class="codeContent panelConte
 nt pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// GET /search?a=a1&amp;a=v2
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// GET /search?a=a1&amp;a=v2
 String exp = searchContext.getSearchExpression();
 assertEquals("(a==a1,a==a2)", exp);
 
@@ -701,15 +701,15 @@ 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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// GET /search?ageFrom=10&amp;ageTill=20
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// GET /search?ageFrom=10&amp;ageTill=20
 String exp = searchContext.getSearchExpression();
 assertEquals("(age=ge=10,age=le=20)", exp);
 </pre>
 </div></div><p>This can allow the plain query expressions mapped to typed bean 
properties and further used with all the existing converters.</p><h2 
id="JAX-RSSearch-SearchExpressionsinURIPathsegments">Search Expressions in URI 
Path segments</h2><p>By default, a FIQL expression is expected to be available 
in either '_s' or '_search' query.<br clear="none"> For example, "find all the 
books with an 'id' property value less than 123":</p><div class="code panel 
pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">GET /books?_s=id=lt=123
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">GET /books?_s=id=lt=123
 </pre>
 </div></div><p>Starting from CXF 2.6.2, it is possible to work with FIQL 
expressions included in URI path segments, for example, the same query can be 
expressed<br clear="none"> in a number of ways:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">GET /books/id=lt=123
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">GET /books/id=lt=123
 GET /books[id=lt=123]
 GET /books(id=lt=123)
 GET /books;id=lt=123
@@ -718,7 +718,7 @@ GET /books;id=lt=123
 
 </pre>
 </div></div><p>Such expressions can be captured in the code using JAX-RS 
annotations:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">@Path("search")
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">@Path("search")
 public class BooksResource {
    @Context
    private SearchContext context;
@@ -765,7 +765,7 @@ public class BooksResource {
 }
 </pre>
 </div></div><p>Note that if you have an expression added to a URI path segment 
with a ";" character acting as a separator, example, "/books;id=lt=123",<br 
clear="none"> or if an expression itself includes ";", example, 
"/books[id=lt=123;id=gt=300]" ("find all the books with id less than 123 or 
greater than 300") <br clear="none"> then a boolean contextual property 
"ignore.matrix.parameters" has to be set to "true" for the runtime to avoid 
splitting the path segment into the path value and matrix parameters.</p><h2 
id="JAX-RSSearch-Queriesinvolvingmultipleentities">Queries involving multiple 
entities</h2><h3 id="JAX-RSSearch-Basicqueries">Basic queries</h3><p>Consider 
the query like "find chapters with a given chapter id from all the books with 
'id' less than 123".<br clear="none"> One easy way to manage such queries is to 
make FIQL and JAX-RS work together. For example:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">@Path("search")
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">@Path("search")
 public class BooksResource {
    @Context
    private SearchContext context;
@@ -798,7 +798,7 @@ public class BooksResource {
 }
 </pre>
 </div></div><h3 id="JAX-RSSearch-Complexqueries">Complex queries</h3><p>In the 
previous section we had the properties of two entities, Book and Chapter, used 
in the query. The query was considered 'simple' because it was really only the 
simple book properties that were checked, and the only chapter property was a 
chapter id, assumed to be equal to a chapter list index.</p><p>Consider "Find 
all the chapters with id less than 5 for all the books with id greater than 
300".</p><p>One way to handle is to follow the example from the previous 
section with few modifications:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">@Path("search")
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">@Path("search")
 public class BooksResource {
    @Context
    private SearchContext context;
@@ -833,7 +833,7 @@ public class BooksResource {
 }
 </pre>
 </div></div><p>In this case two conditions are created and the 2nd condition 
is used to filter the chapters from the books filtered by the 1st 
condition.</p><p>Perhaps a simpler approach, especially in case of JPA2, is to 
start looking for Chapters immediately, assuming Chapter classes have a one to 
one bidirectional relationship with Book:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">public class Chapter {
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">public class Chapter {
    private int id;
    private Book book;
 
@@ -862,7 +862,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">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">SearchConditionBuilder b = 
SearchConditionBuilder.instance();
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">SearchConditionBuilder b = 
SearchConditionBuilder.instance();
 String fiqlQuery = b.is("id").greaterThan(123).query();
 
 WebClient wc = WebClient.create("http://books.com/search";);
@@ -871,7 +871,7 @@ wc.query("_s", fiqlQuery);
 Collection books = wc.getCollection(Book.class);
 </pre>
 </div></div><p>Here is an example of building more complex queries:</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// OR condition
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// OR condition
 String ret = b.is("foo").greaterThan(20).or().is("foo").lessThan(10).query();
 assertEquals("foo=gt=20,foo=lt=10", ret);
 
@@ -886,12 +886,12 @@ String ret = b.is("foo").equalTo(123.4).
 assertEquals("foo==123.4,(bar==asadf*;baz=lt=20.0)", ret);
 </pre>
 </div></div><p>Note, starting from CXF 2.7.1 the following can be used to make 
connecting multiple primitive expressions simpler:</p><div class="code panel 
pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// AND condition, '.and("bar")' is a shortcut for 
"and().is("bar")", similar shortcut is supported for 'or'
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// AND condition, '.and("bar")' is a shortcut for 
"and().is("bar")", similar shortcut is supported for 'or'
 String ret = b.is("foo").greaterThan(20).and("bar").equalTo("plonk").query();
 assertEquals("foo=gt=20;bar==plonk", ret);
 </pre>
 </div></div><p>More updates to the builder API are available on the 
trunk:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// OR condition
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// OR condition
 String ret = b.is("foo").equalTo(20).or().is("foo").equalTo(10).query();
 assertEquals("foo==20,foo==10", ret);
 
@@ -900,7 +900,7 @@ String ret = b.is("foo").equalTo(20, 10)
 assertEquals("foo==20,foo==10", ret);
 </pre>
 </div></div><p>and</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// Connecting composite or() and and() expressions will 
add "()" implicitly:
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// 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);
 
@@ -912,13 +912,13 @@ assertEquals("(foo==20;bar=lt=10),bar=gt
 
 </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: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">?_search=date=le=2010-03-11
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">?_search=date=le=2010-03-11
 </pre>
 </div></div><p>A custom date format can be supported. Use "search.date-format" 
contextual property, example, "search.date-format"="yyyy-MM-dd'T'HH:mm:ss" will 
let users type:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">?_search=time=le=2010-03-11T18:00:00
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">?_search=time=le=2010-03-11T18:00:00
 </pre>
 </div></div><p>If needed, "search.timezone.support" can be enabled to get the 
timezones supported too.</p><p>At the moment, for custom date formats be 
recognized by SearchConditionBuilder, FIQLSearchConditionBuilder has to be 
created explicitly:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">Map&lt;String, String&gt; props = new 
HashMap&lt;String, String&gt;();
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">Map&lt;String, String&gt; props = new 
HashMap&lt;String, String&gt;();
 props.put("search.date-format", "yyyy-MM-dd'T'HH:mm:ss");
 props.put("search.timezone.support", "false");
 
@@ -930,10 +930,10 @@ String ret = bCustom.is("foo").equalTo(d
 assertEquals("foo==2011-03-01T12:34:00", ret);
 </pre>
 </div></div><div class="action-body flooded"><p>&#160;</p><h3 
id="JAX-RSSearch-Relativedates">Relative dates</h3><p>Date value can be 
specified as a duration from the current date/time, as its string 
representation, "PnYnMnDTnHnMnS".<br clear="none"> Resulted date will be 
calculated as a current date + specified duration. For example:</p><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">?_search=date=ge=-P90D
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">?_search=date=ge=-P90D
 </pre>
 </div></div><p>&#160;</p><p>This query will search for a date which is 90 days 
in the past or newer.</p></div><h2 
id="JAX-RSSearch-Alternativequerylanguages">Alternative query 
languages</h2><p>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.</p><h3 
id="JAX-RSSearch-OData">OData</h3><p>&#160;</p><p>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 <a 
shape="rect" class="external-link" 
href="http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerODataSearchTest.java";>test</a>,
 see the startServers function.</p><p>And here is also an XML Spring 
configuration e
 xample (using SearchBean in this specific case):</p><div class="code panel 
pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;"> &lt;cxf:bus&gt;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;"> &lt;cxf:bus&gt;
   &lt;cxf:properties&gt;
     &lt;entry key="search.query.parameter.name" value="$filter" /&gt;
     &lt;entry key="search.parser"&gt;
@@ -945,10 +945,10 @@ assertEquals("foo==2011-03-01T12:34:00",
 &lt;/cxf:bus&gt;
 &#160;</pre>
 </div></div><p>&#160;</p><p>Also note that <a shape="rect" 
class="external-link" href="http://olingo.incubator.apache.org/";>Apache 
Olingo</a> offers its own visitor model which can be used to work with JPA2, 
etc.</p><h2 id="JAX-RSSearch-ContentExtraction">Content 
Extraction</h2><p>Starting from CXF 3.0.2, the content extraction support has 
been added in order to complement the search capabilites with text extraction 
from various document formats (PDF, ODF, DOC,TXT,RTF,...). It is based on 
Apache Tika and is available in two shapes: raw content extraction 
(TikaContentExtractor) and Lucene document content extraction 
(TikaLuceneContentExtractor).</p><h3 
id="JAX-RSSearch-UsingTikaContentExtractor">Using&#160;TikaContentExtractor</h3><p>The
 purpose of Tika content extractor is to provide the essential support of text 
extraction from supported document formats. Additionally, the metadata is being 
extracted as well depending on the document format (author, modified, created, 
pages, ...). 
 The TikaContentExtractor accepts the list of supported parsers and returns the 
extracted metadata together with the desired extracted content format (by 
default raw text). For example:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">TikaContentExtractor extractor = new 
TikaContentExtractor(new PDFParser(), true);
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">TikaContentExtractor extractor = new 
TikaContentExtractor(new PDFParser(), true);
 TikaContent content = extractor .extract( Files.newInputStream( new File( 
"testPDF.pdf" ).toPath() ) );</pre>
 </div></div><p>By default, the TikaContentExtractor&#160; also performs the 
content type detection and validation, which could be turned off using the 
'validateMediaType' constructor argument.</p><h3 
id="JAX-RSSearch-UsingTikaLuceneContentExtractor">Using&#160;TikaLuceneContentExtractor</h3><p>The
 TikaLuceneContentExtractor is very similar to TikaContentExtractor but instead 
of raw content and metadata it returns prepared Lucene document. However, in 
order to properly create the Lucene document which is ready to be indexed, 
TikaLuceneContentExtractor&#160; accepts an additional parameter, 
LuceneDocumentMetadata, with the field types and type converters. For 
example:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">LuceneDocumentMetadata documentMetadata = new 
LuceneDocumentMetadata("contents").withField("modified", Date.class);
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">LuceneDocumentMetadata documentMetadata = new 
LuceneDocumentMetadata("contents").withField("modified", Date.class);
 TikaLuceneContentExtractor extractor = new TikaLuceneContentExtractor(new 
PDFParser(), true);
 Document document = extractor.extract( Files.newInputStream( new File( 
"testPDF.pdf" ).toPath() ), documentMetadata  );</pre>
 </div></div><p>At this point, the document is ready to be analyzed and 
indexed. The TikaLuceneContentExtractor uses&#160;LuceneDocumentMetadata to 
create the properly typed document fields and currently supports DoubleField, 
FloatField, LongField, IntField,&#160;IntField,&#160;TextField (for content) 
and StringField (also used to store dates).</p><p>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 <a shape="rect" class="external-link" 
href="https://github.com/apache/cxf/tree/master/distribution/src/main/release/samples/jax_rs/search";
 rel="nofollow">official Apache CXF Github repository</a>. 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&#160; phrase search).</p><pre>&#160;</pre></div>

Modified: websites/production/cxf/content/docs/jax-rs-validation.html
==============================================================================
--- websites/production/cxf/content/docs/jax-rs-validation.html (original)
+++ websites/production/cxf/content/docs/jax-rs-validation.html Wed Sep 13 
15:05:52 2017
@@ -108,11 +108,11 @@ Apache CXF -- JAX-RS Validation
            <!-- Content -->
            <div class="wiki-content">
 <div id="ConfluenceContent"><h1 
id="JAX-RSValidation-JAX-RSBeanValidation">JAX-RS Bean 
Validation</h1><p>&#160;</p><p><style type="text/css">/*<![CDATA[*/
-div.rbtoc1505311251102 {padding: 0px;}
-div.rbtoc1505311251102 ul {list-style: disc;margin-left: 0px;}
-div.rbtoc1505311251102 li {margin-left: 0px;padding-left: 0px;}
+div.rbtoc1505314861355 {padding: 0px;}
+div.rbtoc1505314861355 ul {list-style: disc;margin-left: 0px;}
+div.rbtoc1505314861355 li {margin-left: 0px;padding-left: 0px;}
 
-/*]]>*/</style></p><div class="toc-macro rbtoc1505311251102">
+/*]]>*/</style></p><div class="toc-macro rbtoc1505314861355">
 <ul class="toc-indentation"><li><a shape="rect" 
href="#JAX-RSValidation-JAX-RSBeanValidation">JAX-RS Bean 
Validation</a></li></ul>
 </div></div>
            </div>

Modified: websites/production/cxf/content/docs/jax-rs-xml-security.html
==============================================================================
--- websites/production/cxf/content/docs/jax-rs-xml-security.html (original)
+++ websites/production/cxf/content/docs/jax-rs-xml-security.html Wed Sep 13 
15:05:52 2017
@@ -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/shBrushJava.js'></script>
 <script src='/resources/highlighter/scripts/shBrushXml.js'></script>
+<script src='/resources/highlighter/scripts/shBrushJava.js'></script>
 <script>
   SyntaxHighlighter.defaults['toolbar'] = false;
   SyntaxHighlighter.all();
@@ -121,25 +121,25 @@ Apache CXF -- JAX-RS XML Security
 
 
 &#160;</p><p>&#160;</p><p>&#160;</p><p>&#160;</p><p><style 
type="text/css">/*<![CDATA[*/
-div.rbtoc1505311243324 {padding: 0px;}
-div.rbtoc1505311243324 ul {list-style: disc;margin-left: 0px;}
-div.rbtoc1505311243324 li {margin-left: 0px;padding-left: 0px;}
+div.rbtoc1505314988251 {padding: 0px;}
+div.rbtoc1505314988251 ul {list-style: disc;margin-left: 0px;}
+div.rbtoc1505314988251 li {margin-left: 0px;padding-left: 0px;}
 
-/*]]>*/</style></p><div class="toc-macro rbtoc1505311243324">
+/*]]>*/</style></p><div class="toc-macro rbtoc1505314988251">
 <ul class="toc-indentation"><li><a shape="rect" 
href="#JAX-RSXMLSecurity-Introduction">Introduction</a></li><li><a shape="rect" 
href="#JAX-RSXMLSecurity-Mavendependencies">Maven dependencies</a></li><li><a 
shape="rect" 
href="#JAX-RSXMLSecurity-Backwardscompatibilityconfigurationnote">Backwards 
compatibility configuration note</a></li><li><a shape="rect" 
href="#JAX-RSXMLSecurity-XMLSignature">XML Signature</a>
 <ul class="toc-indentation"><li><a shape="rect" 
href="#JAX-RSXMLSecurity-Envelopedsignatures">Enveloped 
signatures</a></li><li><a shape="rect" 
href="#JAX-RSXMLSecurity-Envelopingsignatures">Enveloping 
signatures</a></li><li><a shape="rect" 
href="#JAX-RSXMLSecurity-Detachedsignatures">Detached signatures</a></li><li><a 
shape="rect" href="#JAX-RSXMLSecurity-Customizingthesignature">Customizing the 
signature</a></li><li><a shape="rect" 
href="#JAX-RSXMLSecurity-SignatureKeyInfoValidation">Signature Key Info 
Validation</a></li></ul>
 </li><li><a shape="rect" href="#JAX-RSXMLSecurity-XMLEncryption">XML 
Encryption</a>
 <ul class="toc-indentation"><li><a shape="rect" 
href="#JAX-RSXMLSecurity-Usingtherequestsignaturecertificatesfortheencryption">Using
 the request signature certificates for the encryption</a></li><li><a 
shape="rect" href="#JAX-RSXMLSecurity-Customizingtheencryption">Customizing the 
encryption</a></li><li><a shape="rect" 
href="#JAX-RSXMLSecurity-GCMAlgorithmandBouncyCastleprovider">GCM Algorithm and 
BouncyCastle provider</a></li></ul>
 </li><li><a shape="rect" 
href="#JAX-RSXMLSecurity-Restrictingencryptionandsignaturealgorithms">Restricting
 encryption and signature algorithms</a></li><li><a shape="rect" 
href="#JAX-RSXMLSecurity-Interoperability">Interoperability</a></li></ul>
 </div><h1 id="JAX-RSXMLSecurity-Introduction">Introduction</h1><p>CXF 2.5.0 
introduces an initial support for securing JAX-RS clients and endpoints with <a 
shape="rect" class="external-link" href="http://www.w3.org/TR/xmldsig-core/"; 
rel="nofollow">XML Signature</a> and <a shape="rect" class="external-link" 
href="http://www.w3.org/TR/xmlenc-core/"; rel="nofollow">XML Encryption</a>. <br 
clear="none"> This is a work in progress and the enhancements will be applied 
regularly. Support for the alternative signature and encryption technologies 
will also be provided in due time.</p><h1 
id="JAX-RSXMLSecurity-Mavendependencies">Maven dependencies</h1><div 
class="code panel pdl" style="border-width: 1px;"><div class="codeContent 
panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">&lt;dependency&gt;
+<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-security-xml&lt;/artifactId&gt;
   &lt;version&gt;2.5.2&lt;/version&gt;
 &lt;/dependency&gt;
 </pre>
 </div></div><h1 
id="JAX-RSXMLSecurity-Backwardscompatibilityconfigurationnote">Backwards 
compatibility configuration note</h1><p>From Apache CXF 3.1.0, the WS-Security 
based configuration tags used to configure XML Signature or Encryption 
("ws-security-*") have been changed to just start with "security-". Apart from 
this they are exactly the same. Older "ws-security-" values continue to be 
accepted in CXF 3.1.0. To use any of the configuration examples in this page 
with an older version of CXF, simply add a "ws-" prefix to the configuration 
tag.</p><h1 id="JAX-RSXMLSecurity-XMLSignature">XML Signature</h1><p><a 
shape="rect" class="external-link" href="http://www.w3.org/TR/xmldsig-core/"; 
rel="nofollow">XML Signature</a> defines 3 types of signatures: enveloped, 
enveloping and detached. All the three types are supported by CXF 
JAX-RS.</p><p><strong>New</strong> Starting from CXF 2.5.2 it is also possible 
to add XML Signatures on the server side and get them validated on the client 
sid
 e.</p><h2 id="JAX-RSXMLSecurity-Envelopedsignatures">Enveloped 
signatures</h2><p>Payload:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">&lt;Book ID="4bd59819-7b78-47a5-bb61-cc08348e9d48"&gt;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">&lt;Book ID="4bd59819-7b78-47a5-bb61-cc08348e9d48"&gt;
    &lt;id&gt;126&lt;/id&gt;
    &lt;name&gt;CXF&lt;/name&gt;
 
@@ -181,7 +181,7 @@ JakFtKBP++EC9rNNpZnqqHxx3qb2tW25qRtBzDmK
 &lt;/Book&gt;
 </pre>
 </div></div><p>Note that the Book root element is signed including its name 
and id children, and a signature ds:Reference links to Book.</p><p>Server 
Configuration fragment:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">&lt;bean id="serviceBean" 
class="org.apache.cxf.systest.jaxrs.security.BookStore"/&gt;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">&lt;bean id="serviceBean" 
class="org.apache.cxf.systest.jaxrs.security.BookStore"/&gt;
 &lt;bean id="xmlSigHandler" 
class="org.apache.cxf.rs.security.xml.XmlSigInHandler"/&gt;
 &lt;bean id="xmlSigOutHandler" 
class="org.apache.cxf.rs.security.xml.XmlSigOutInterceptor"/&gt;
 
@@ -213,7 +213,7 @@ JakFtKBP++EC9rNNpZnqqHxx3qb2tW25qRtBzDmK
 
 </pre>
 </div></div><p>Note that org.apache.cxf.rs.security.xml.XmlSigInHandler is 
responsible for validating the signature attached to the inbound payload and is 
capable of processing all 3 types of XML 
Signature.</p><p>org.apache.cxf.rs.security.xml.XmlSigOutInterceptor is 
responsible for adding a new signature to the outbound payload.</p><p>Client 
code:</p><div class="code panel pdl" style="border-width: 1px;"><div 
class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">String address = 
"https://localhost:8080/xmlsig/bookstore/books";;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">String address = 
"https://localhost:8080/xmlsig/bookstore/books";;
 JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
 bean.setAddress(address);
 
@@ -245,7 +245,7 @@ WebClient wc = bean.createWebClient();
 Book book = wc.post(new Book("CXF", 126L), Book.class);
 </pre>
 </div></div><p>Spring configuration can also be used.<br clear="none"> Please 
also check <a shape="rect" href="secure-jax-rs-services.html">Secure JAX-RS 
Services</a> on how HTTPS can be configured from Spring.</p><h2 
id="JAX-RSXMLSecurity-Envelopingsignatures">Enveloping 
signatures</h2><p>Payload:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">&lt;ds:Signature 
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"&gt;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">&lt;ds:Signature 
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"&gt;
    &lt;ds:SignedInfo&gt;
       &lt;ds:CanonicalizationMethod 
Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/&gt;
       &lt;ds:SignatureMethod 
Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/&gt;
@@ -277,13 +277,13 @@ Book book = wc.post(new Book("CXF", 126L
 &lt;/ds:Signature&gt;
 </pre>
 </div></div><p>This time the signature is enveloping the Book element using a 
ds:Object wrapper which ds:Reference links to.</p><p>Server Configuration 
fragment is identical to the one shown in the Enveloped signatures 
section.</p><p>Client code is nearly identical to the one shown in the 
Enveloped signatures section except that XmlSigOutInterceptor need to have an 
additional property set:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// add the interceptor dealing with adding a signature
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// add the interceptor dealing with adding a signature
 XmlSigOutInterceptor sigInterceptor = new XmlSigOutInterceptor();
 sigInterceptor.setStyle("enveloping");
 
 </pre>
 </div></div><h2 id="JAX-RSXMLSecurity-Detachedsignatures">Detached 
signatures</h2><p>Payload:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">&lt;env:Envelope 
xmlns:env="http://org.apache.cxf/rs/env"&gt;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">&lt;env:Envelope 
xmlns:env="http://org.apache.cxf/rs/env"&gt;
 
   &lt;Book ID="e9836bc2-cb5a-453f-b967-a9ddbaf9a6de"&gt;
     &lt;id&gt;125&lt;/id&gt;
@@ -330,13 +330,13 @@ sigInterceptor.setStyle("enveloping");
 &lt;/env:Envelope&gt;
 </pre>
 </div></div><p>Note that the whole payload is enveloped by a configurable 
element wrapper. The Book instance is one part of the envelope and it's signed 
by a detached signature (see the first ds:Signature, with its ds:Reference 
linking to Book). The envelope also has an embedded SAML assertion which has 
its own enveloped signature.</p><p>The instance of 
org.apache.cxf.rs.security.xml.XmlSigInHandler will handle a detached XML 
signature of the Book XML fragment on the server side. See the <a shape="rect" 
href="jax-rs-saml.html">JAX-RS SAML</a> for more info on how to deal with SAML 
assertions.</p><p>Client code is nearly identical to the one shown in the 
Enveloped signatures section except that XmlSigOutInterceptor need to have an 
additional property set:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// add the interceptor dealing with adding a signature
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// add the interceptor dealing with adding a signature
 XmlSigOutInterceptor sigInterceptor = new XmlSigOutInterceptor();
 sigInterceptor.setStyle("detached");
 
 </pre>
 </div></div><h2 id="JAX-RSXMLSecurity-Customizingthesignature">Customizing the 
signature</h2><p>org.apache.cxf.rs.security.xml.XmlSigOutInterceptor manages 
the creation of the signature on the client side.<br clear="none"> The 
following properties can be set on it at the moment:</p><p>"style": possible 
values are "enveloped" (default), "enveloping" and "detached"<br clear="none"> 
"envelopedName": only used with the "detached" style, default is "{<a 
shape="rect" class="external-link" href="http://org.apache.cxf/rs/env"; 
rel="nofollow">http://org.apache.cxf/rs/env</a>}Envelope"<br clear="none"> 
"signatureAlgorithm": default is 
"http://www.w3.org/2000/09/xmldsig#rsa-sha1";<br clear="none"> 
"digestAlgorithm": default is "http://www.w3.org/2000/09/xmldsig#sha1";</p><h2 
id="JAX-RSXMLSecurity-SignatureKeyInfoValidation">Signature Key Info 
Validation</h2><p>By default ds:Signature is expected to contain ds:KeyInfo 
element.</p><p>Setting a "keyInfoMustBeAvailable" property to false on the out i
 nterceptors will lead to KeyInfo not included.</p><p>If the same property is 
set to false on the in interceptors then either an authenticated Principal name 
or a default store alias will be used to load the certificate for validating 
the signature.</p><h1 id="JAX-RSXMLSecurity-XMLEncryption">XML 
Encryption</h1><p>Encrypting XML payloads makes it possible to drop a 
requirement for HTTPS.</p><p>Here is a payload example:</p><div class="code 
panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">&lt;xenc:EncryptedData 
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"&gt;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">&lt;xenc:EncryptedData 
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"&gt;
   &lt;xenc:EncryptionMethod 
Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/&gt;
   &lt;ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"&gt;
     &lt;ds:RetrievalMethod 
Type="http://www.w3.org/2001/04/xmlenc#EncryptedKey"/&gt;
@@ -358,7 +358,7 @@ sigInterceptor.setStyle("detached");
 &lt;/xenc:EncryptedData&gt;
 </pre>
 </div></div><p>Here is a server configuration fragment:</p><div class="code 
panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">&lt;bean id="serviceBean" 
class="org.apache.cxf.systest.jaxrs.security.BookStore"/&gt;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">&lt;bean id="serviceBean" 
class="org.apache.cxf.systest.jaxrs.security.BookStore"/&gt;
 &lt;bean id="xmlSigInHandler" 
class="org.apache.cxf.rs.security.xml.XmlSigInHandler"/&gt;
 &lt;bean id="xmlEncInHandler" 
class="org.apache.cxf.rs.security.xml.XmlEncInHandler"/&gt;
     
@@ -382,7 +382,7 @@ sigInterceptor.setStyle("detached");
 
 </pre>
 </div></div><p>This configuration supports receiving signed and then encrypted 
XML payloads.</p><p>The code:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">String address = 
"https://localhost:8080/xmlencryption/bookstore/books";;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">String address = 
"https://localhost:8080/xmlencryption/bookstore/books";;
 JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
 bean.setAddress(address);
 
@@ -419,7 +419,7 @@ Response r = wc.post(new Book("CXF", 126
 assertEquals(200, r.getStatus());
 </pre>
 </div></div><p>Note that XmlEncOutInterceptor interceptor has a 
"symmetricEncAlgorithm" property set to a weaker type just to get CXF tests 
passing.</p><p>The actual application client code does not expect a payload 
such as Book back but if it did then configuring the server to encrypt the 
response would be straightforward:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">&lt;bean id="serviceBean" 
class="org.apache.cxf.systest.jaxrs.security.BookStore"/&gt;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">&lt;bean id="serviceBean" 
class="org.apache.cxf.systest.jaxrs.security.BookStore"/&gt;
 &lt;bean id="xmlSigInHandler" 
class="org.apache.cxf.rs.security.xml.XmlSigInHandler"/&gt;
 &lt;bean id="xmlSigOutHandler" 
class="org.apache.cxf.rs.security.xml.XmlSigOutInterceptor"/&gt;
 
@@ -452,14 +452,14 @@ assertEquals(200, r.getStatus());
 &lt;/jaxrs:server&gt;
 </pre>
 </div></div><p>Now the client code can be updated to expect an encrypted and 
signed Book back:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">// Use the previous code fragment, add the in 
interceptors:
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">// Use the previous code fragment, add the in 
interceptors:
 XmlEncInInterceptor encInInterceptor = new XmlEncInInterceptor();
 bean.getInInterceptors().add(encInInterceptor);
 XmlSigInInterceptor sigInInterceptor = new XmlSigInInterceptor();
 bean.getInInterceptors().add(sigInInterceptor);
 </pre>
 </div></div><h2 
id="JAX-RSXMLSecurity-Usingtherequestsignaturecertificatesfortheencryption">Using
 the request signature certificates for the encryption</h2><p><strong>From CXF 
2.6.1 and 2.5.4:</strong></p><p>When multiple clients are posting the encrypted 
and signed payloads, the following configuration will lead to the request 
signature certificates being utilized for encrypting the symmetric key used to 
encrypt the response:</p><div class="code panel pdl" style="border-width: 
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">&lt;!-- server --&gt;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">&lt;!-- server --&gt;
 &lt;jaxrs:server&gt;
 &lt;jaxrs:properties&gt;
          &lt;entry key="security.callback-handler" 
@@ -486,7 +486,7 @@ bean.getInInterceptors().add(sigInInterc
 &lt;/jaxrs:client&gt;
 </pre>
 </div></div><p>The "security.encryption.username" server property is set to 
"useReqSigCert".</p><p>Note that the client configuration assumes Alice (with 
its alice.properties) represents a given client, Bob (with its bob.properties) 
- the receiver/server.</p><p>On the server side the encryption properties point 
to alice.properties and signature.properties to bob.properties. This is because 
the outbound signature needs to be done with the Bob's certificate and the 
encryption - with either the specific Alice's certificate or the certificate 
from the inbound signature. Note that the in encryption handler will check the 
signature properties first - this will ensure that the Bob's certificate used 
to encrypt the data on the client side can be validated, similarly for the in 
signature handler.</p><h2 
id="JAX-RSXMLSecurity-Customizingtheencryption">Customizing the 
encryption</h2><p>org.apache.cxf.rs.security.xml.XmlEncOutInterceptor manages 
the encryption process.<br clear="none"> The foll
 owing properties can be set on it at the moment:<br clear="none"> 
"symmetricEncAlgorithm": default is 
"http://www.w3.org/2001/04/xmlenc#aes256-cbc";, complete URIs or short 
identifiers are supported, for example, "aes128-cbc" or 
"http://www.w3.org/2001/04/xmlenc#aes256-cbc";. <br clear="none"> 
"digestAlgorithm": optional, example "http://www.w3.org/2001/04/xmlenc#sha256"; 
can be set.<br clear="none"> "keyEncAlgorithm": default is 
"http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p";<br clear="none"> 
"keyIdentifierType": default is "X509_KEY", "X509_ISSUER_SERIAL" is also 
supported - useful when the whole x509Certificate should not be embedded</p><h2 
id="JAX-RSXMLSecurity-GCMAlgorithmandBouncyCastleprovider">GCM Algorithm and 
BouncyCastle provider</h2><p>Please see Colm's <a shape="rect" 
class="external-link" 
href="http://coheigea.blogspot.com/2012/04/note-on-cve-2011-1096.html"; 
rel="nofollow">blog</a> for the information about the possible attack against 
XML Encryption and the GCM algorith
 m which needs to be used in order to prevent it.</p><h1 
id="JAX-RSXMLSecurity-Restrictingencryptionandsignaturealgorithms">Restricting 
encryption and signature algorithms</h1><p><strong>From CXF 2.6.1 and 
2.5.4:</strong></p><p>It is possible to configure the in encryption and 
signature handlers with the properties restricting the encryption and signature 
algorithms that clients can use, for example:</p><div class="code panel pdl" 
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: bash; gutter: false; theme: Confluence" 
style="font-size:12px;">    &lt;bean id="sigProps" 
class="org.apache.cxf.rs.security.xml.SignatureProperties"&gt;
+<pre class="brush: java; gutter: false; theme: Default" 
style="font-size:12px;">    &lt;bean id="sigProps" 
class="org.apache.cxf.rs.security.xml.SignatureProperties"&gt;
        &lt;property name="signatureAlgo" 
                  value="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/&gt;
        &lt;property name="signatureDigestAlgo" 


Reply via email to