You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by bu...@apache.org on 2015/09/01 13:08:06 UTC

svn commit: r963847 - in /websites/staging/olingo/trunk/content: ./ doc/odata4/tutorials/sqo_o/ doc/odata4/tutorials/sqo_o/products_bynameasc.png doc/odata4/tutorials/sqo_o/products_unsorted.png doc/odata4/tutorials/sqo_o/tutorial_sqo_o.html

Author: buildbot
Date: Tue Sep  1 11:08:06 2015
New Revision: 963847

Log:
Staging update by buildbot for olingo

Added:
    websites/staging/olingo/trunk/content/doc/odata4/tutorials/sqo_o/
    websites/staging/olingo/trunk/content/doc/odata4/tutorials/sqo_o/products_bynameasc.png   (with props)
    websites/staging/olingo/trunk/content/doc/odata4/tutorials/sqo_o/products_unsorted.png   (with props)
    websites/staging/olingo/trunk/content/doc/odata4/tutorials/sqo_o/tutorial_sqo_o.html
Modified:
    websites/staging/olingo/trunk/content/   (props changed)

Propchange: websites/staging/olingo/trunk/content/
------------------------------------------------------------------------------
--- cms:source-revision (original)
+++ cms:source-revision Tue Sep  1 11:08:06 2015
@@ -1 +1 @@
-1696778
+1700486

Added: websites/staging/olingo/trunk/content/doc/odata4/tutorials/sqo_o/products_bynameasc.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/olingo/trunk/content/doc/odata4/tutorials/sqo_o/products_bynameasc.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/olingo/trunk/content/doc/odata4/tutorials/sqo_o/products_unsorted.png
==============================================================================
Binary file - no diff available.

Propchange: websites/staging/olingo/trunk/content/doc/odata4/tutorials/sqo_o/products_unsorted.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: websites/staging/olingo/trunk/content/doc/odata4/tutorials/sqo_o/tutorial_sqo_o.html
==============================================================================
--- websites/staging/olingo/trunk/content/doc/odata4/tutorials/sqo_o/tutorial_sqo_o.html (added)
+++ websites/staging/olingo/trunk/content/doc/odata4/tutorials/sqo_o/tutorial_sqo_o.html Tue Sep  1 11:08:06 2015
@@ -0,0 +1,390 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html lang="en">
+  <head>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="description" content="Apache Olingo provides libraries which enable developers to implement OData producers and OData consumers. The available OData Java library implements OData version 2.0. In future on goal is to provide an OData 4.0 compliant library once the OData standard is published at OASIS. The focus within the community is currently on the Java technology but it is up to the community to discuss if other environments find interest.">
+    <meta name="author" content="">
+    <link rel="icon" href="/favicon.ico">
+    <title>
+      Apache Olingo Library
+    </title><!-- Bootstrap core CSS -->
+    <link href="/css/bootstrap.css" rel="stylesheet" type="text/css"><!-- Custom styles for this template -->
+    <link href="/css/navbar.css" rel="stylesheet" type="text/css"><!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
+    <link href="/css/offcanvas.css" rel="stylesheet" type="text/css"><!-- Custom styles for this template -->
+    <link rel="stylesheet" href="/css/main.css">
+    <!--[if lt IE 9]><script src="/js/ie8-responsive-file-warning.js"></script><![endif]-->
+
+    <script src="/js/ie-emulation-modes-warning.js" type="text/javascript">
+</script><!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
+
+    <script src="/js/ie10-viewport-bug-workaround.js" type="text/javascript">
+</script><!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
+    <!--[if lt IE 9]>
+      <script src="/js/html5shiv.min.js"></script>
+      <script src="/js/respond.min.js"></script>
+    <![endif]-->
+  </head>
+
+  <body>
+    <div class="container">
+      <!-- Static navbar -->
+      <div class="navbar navbar-default" role="navigation">
+        <div class="container-fluid">
+          <div class="navbar-header">
+            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
+              <span class="sr-only">Toggle navigation</span>
+             <span class="icon-bar"></span>
+             <span class="icon-bar"></span>
+             <span class="icon-bar"></span>
+            </button>
+              <img class="navbar-brand" src="/img/OlingoOrangeTM.png" style="width:62px;" >
+              <a class="navbar-brand" href="#">Apache Olingo™</a>
+          </div>
+          <div class="navbar-collapse collapse">
+            <ul class="nav navbar-nav">
+
+              <li><a href="/">Home</a></li>
+              <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">ASF <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                      <li><a href="http://www.apache.org/foundation/">ASF Home</a></li>
+                      <li><a href="http://projects.apache.org/">Projects</a></li>
+                      <li><a href="http://people.apache.org/">People</a></li>
+                      <li><a href="http://www.apache.org/foundation/getinvolved.html">Get Involved</a></li>
+                      <li><a href="http://www.apache.org/dyn/closer.cgi">Download</a></li>
+                      <li><a href="http://www.apache.org/security/">Security</a></li>
+                      <li><a href="http://www.apache.org/foundation/sponsorship.html">Support Apache</a></li>
+                  </ul>
+              </li>
+
+              <li><a href="http://www.apache.org/licenses/">License</a></li>
+
+              <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Download <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                      <li><a href="/doc/odata2/download.html">Download OData 2.0 Java</a></li>
+                      <li><a href="/doc/odata4/download.html">Download OData 4.0 Java</a></li>
+                      <li><a href="/doc/javascript/download.html">Download OData 4.0 JavaScript</a></li>
+                  </ul>
+              </li>
+
+              <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Documentation <b class="caret"></b></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="/doc/odata2/index.html">Documentation OData 2.0 Java</a></li>
+                    <li><a href="/doc/odata4/index.html">Documentation OData 4.0 Java</a></li>
+                    <li><a href="/doc/javascript/index.html">Documentation OData 4.0 JavaScript</a></li>
+                  </ul>
+              </li>
+              <li><a href="/support.html">Support</a></li>
+
+            </ul>
+
+			  <img class="navbar-right" height="50px" src="/img/asf-logo.gif">
+
+			</div><!--/.nav-collapse -->
+        </div><!--/.container-fluid -->
+      </div><!-- Main component for a primary marketing message or call to action --><style type="text/css">
+/* The following code is added by mdx_elementid.py
+   It was originally lifted from http://subversion.apache.org/style/site.css */
+/*
+ * Hide class="elementid-permalink", except when an enclosing heading
+ * has the :hover property.
+ */
+.headerlink, .elementid-permalink {
+  visibility: hidden;
+}
+h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
+<h1 id="how-to-build-an-odata-service-with-olingo-v4">How to build an OData Service with Olingo V4<a class="headerlink" href="#how-to-build-an-odata-service-with-olingo-v4" title="Permanent link">&para;</a></h1>
+<h1 id="part-53-system-query-options-orderby">Part 5.3: System Query Options: $orderby<a class="headerlink" href="#part-53-system-query-options-orderby" title="Permanent link">&para;</a></h1>
+<h2 id="introduction">Introduction<a class="headerlink" href="#introduction" title="Permanent link">&para;</a></h2>
+<p>In the present tutorial, we’ll continue implementing OData system query options, this time focusing on <strong>$orderby</strong></p>
+<p><strong>Note:</strong>
+The full implementation of the OData service as described in the present tutorial can be found in the attached zip file that contains an Eclipse project that can be imported into your Eclipse workspace.</p>
+<p><strong>Disclaimer:</strong>
+Again, in the present tutorial, we’ll focus only on the relevant implementation, in order to keep the code small and simple. The sample code as it is, shouldn’t be reused for advanced scenarios.</p>
+<p><strong>Table of Contents</strong></p>
+<div class="codehilite"><pre>1<span class="p">.</span>  <span class="n">Prerequisites</span>
+2<span class="p">.</span>  <span class="n">Preparation</span>
+3<span class="p">.</span>  <span class="n">Implementation</span>
+         1<span class="p">.</span><span class="n">Implement</span> $<span class="n">ordergy</span> 
+4<span class="p">.</span>  <span class="n">Run</span> <span class="n">the</span> <span class="n">implemented</span> <span class="n">service</span>
+5<span class="p">.</span>  <span class="n">Summary</span>
+6<span class="p">.</span>  <span class="n">Links</span>
+</pre></div>
+
+
+<p>__</p>
+<h1 id="1-prerequisites">1. Prerequisites<a class="headerlink" href="#1-prerequisites" title="Permanent link">&para;</a></h1>
+<p>Same prerequisites as in <a href="http://olingo.apache.org/doc/odata4/tutorials/read/tutorial_read.html">Tutorial Part 1: Read Entity Collection</a>
+ and <a href="http://olingo.apache.org/doc/odata4/tutorials/readep/tutorial_readep.html">Tutorial Part 2: Read Entity</a> as well as basic knowledge about the concepts presented in both tutorials.</p>
+<p>Furthermore, Tutorial Part 5.1 should have been read.</p>
+<h1 id="2-preparation">2. Preparation<a class="headerlink" href="#2-preparation" title="Permanent link">&para;</a></h1>
+<p>Follow <em>Tutorial Part 1: Read Entity Collection</em> and <em>Tutorial Part 2: Read Entity</em> or as shortcut import the <a href="http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip">project</a> attached to Tutorial Part 2 into your Eclipse workspace.</p>
+<p>Afterwards do a <em>Deploy and run</em>: it should be working.</p>
+<h1 id="implementation">Implementation<a class="headerlink" href="#implementation" title="Permanent link">&para;</a></h1>
+<p>The system query options we’re focusing on are applied to the entity collection only, therefore our 
+implementation for all three query options is done in the class
+<em>myservice.mynamespace.service.DemoEntityCollectionProcessor</em></p>
+<p>The general sequence is again:</p>
+<ol>
+<li>Analyze the URI</li>
+<li>Fetch data from backend</li>
+<li>Apply the system query option</li>
+<li>Serialize</li>
+<li>Configure the response</li>
+</ol>
+<h2 id="31-implement-orderby">3.1. Implement $orderby<a class="headerlink" href="#31-implement-orderby" title="Permanent link">&para;</a></h2>
+<p><strong>Background</strong></p>
+<p>When requesting a list of entities from a service, it is up to the service implementation to decide in which order they are presented. This can depend on the backend data source, anyways, it is undefined.
+But the consumer of an OData service might want to be able to specify the order, according to his needs. </p>
+<p>For example, a usual case would be that the list of entities is sorted as per default by its ID number, but for a user, the ID is not relevant and he would prefer a sorting e.g. by the name
+OData supports this requirement with the system query option <strong>$orderby</strong>
+It is specified as follows:</p>
+<div class="codehilite"><pre>$<span class="n">orderby</span><span class="p">=</span><span class="o">&lt;</span><span class="n">propertyName</span><span class="o">&gt;</span>
+</pre></div>
+
+
+<p>The order can be ascending or descending:</p>
+<div class="codehilite"><pre>$<span class="n">orderby</span><span class="p">=</span><span class="o">&lt;</span><span class="n">propertyName</span><span class="o">&gt;</span> <span class="n">asc</span>
+$<span class="n">orderby</span><span class="p">=</span><span class="o">&lt;</span><span class="n">propertyName</span><span class="o">&gt;</span> <span class="n">desc</span>
+</pre></div>
+
+
+<p>If not specified, the default is ascending.</p>
+<p>See here for more details:
+<a href="http://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/part1-protocol/odata-v4.0-errata02-os-part1-protocol-complete.html#_Toc406398305">OData Version 4.0 Part 1: Protocol Plus Errata 02</a></p>
+<p><strong>Note:</strong>
+As of the OData specification, the $orderby system query option can be applied to multiple properties.
+In that case, the value is specified as comma-separated list.</p>
+<p><strong>Example:</strong></p>
+<div class="codehilite"><pre><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">localhost</span><span class="p">:</span>8080<span class="o">/</span><span class="n">DemoService</span><span class="o">/</span><span class="n">DemoService</span><span class="p">.</span><span class="n">svc</span><span class="o">/</span><span class="n">Products</span>?$<span class="n">orderby</span><span class="p">=</span><span class="n">Name</span> <span class="n">asc</span><span class="p">,</span> <span class="n">Description</span> <span class="n">desc</span>
+</pre></div>
+
+
+<p>In this example, all the products are sorted by their name. Moreover, all products with the same name are sorted by their description in descending order.
+Another example could be that I want to display all my customers, they should be sorted by their country. Additionally, within each country, they should be sorted by their name</p>
+<p>In order to support such sorting, the OData service implementation has to make use of the <em>ExpressionVisitor</em> concept.
+We haven’t used it in the present tutorial, because the ExpressionVisitor will be explained in the $filter section</p>
+<p><strong>Example</strong>
+First, just to remember how the full payload looks like, the “normal” query of the product:
+<a href="http://localhost:8080/DemoService/DemoService.svc/Products">http://localhost:8080/DemoService/DemoService.svc/Products</a></p>
+<p><img alt="AllProductsNotSorted" src="products_unsorted.png" title="All products not sorted" /></p>
+<p>The following request specifies the sorting by the name. 
+The order is ascending, if not specified elsewise.</p>
+<p><a href="http://localhost:8080/DemoService/DemoService.svc/Products?$orderby=Name">http://localhost:8080/DemoService/DemoService.svc/Products?$orderby=Name</a></p>
+<p><img alt="ProductsOrderedByNameAsc" src="products_bynameasc.png" title="All products sorted by name ascending" /></p>
+<p><strong>Implementation</strong></p>
+<p>The following section describes the simple approach to enable the <em>EntityCollectionProcessor</em> class and the <em>readEntityCollection()</em> method for <em>$orderby</em>.</p>
+<p>Just like in the previous tutorials, the data is first fetched from the backend, then the system query option is applied.</p>
+<div class="codehilite"><pre><span class="n">EntityCollection</span> <span class="n">entityCollection</span> <span class="o">=</span> <span class="n">storage</span><span class="o">.</span><span class="na">readEntitySetData</span><span class="o">(</span><span class="n">edmEntitySet</span><span class="o">);</span>
+<span class="n">List</span><span class="o">&lt;</span><span class="n">Entity</span><span class="o">&gt;</span> <span class="n">entityList</span> <span class="o">=</span> <span class="n">entityCollection</span><span class="o">.</span><span class="na">getEntities</span><span class="o">();</span>
+</pre></div>
+
+
+<p>We will proceed according to these 4 steps:</p>
+<ol>
+<li>Get the query option from the <em>UriInfo</em>. If null is returned then nothing has to be done.</li>
+<li>Get the value from the query option</li>
+<li>Analyze the value</li>
+<li>Modify the <em>EntityCollection</em></li>
+</ol>
+<p><strong>1. Get the OrderByOption from the UriInfo:</strong></p>
+<div class="codehilite"><pre><span class="n">OrderByOption</span> <span class="n">orderByOption</span> <span class="o">=</span> <span class="n">uriInfo</span><span class="o">.</span><span class="na">getOrderByOption</span><span class="o">();</span>
+<span class="k">if</span> <span class="o">(</span><span class="n">orderByOption</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
+</pre></div>
+
+
+<p><strong>2. Get the value of the OrderByOption:</strong></p>
+<div class="codehilite"><pre><span class="n">List</span><span class="o">&lt;</span><span class="n">OrderByItem</span><span class="o">&gt;</span> <span class="n">orderItemList</span> <span class="o">=</span> <span class="n">orderByOption</span><span class="o">.</span><span class="na">getOrders</span><span class="o">();</span>
+<span class="kd">final</span> <span class="n">OrderByItem</span> <span class="n">orderByItem</span> <span class="o">=</span> <span class="n">orderItemList</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
+</pre></div>
+
+
+<p>The instance of an OrderByOption can be asked for the list of its <em>OrderByItems</em>.
+Why a list?
+Because the $orderby expression can be composed with multiple properties
+For example, for the following URL, we get 2 OrderByItems:</p>
+<div class="codehilite"><pre><span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">localhost</span><span class="p">:</span>8080<span class="o">/</span><span class="n">DemoService</span><span class="o">/</span><span class="n">DemoService</span><span class="p">.</span><span class="n">svc</span><span class="o">/</span><span class="n">Products</span>?$<span class="n">orderby</span><span class="p">=</span><span class="n">Name</span> <span class="n">asc</span><span class="p">,</span> <span class="n">Description</span> <span class="n">desc</span>
+</pre></div>
+
+
+<p>In our example, we support only one property, therefore we directly access the first OrderByItem in the list.</p>
+<p><strong>3. Analyze the value</strong></p>
+<p>What do we want to do?
+From the backend we got a list of entities that are products. We want to apply a sorter to that list and we want to sort by the property name that is given in the URI.
+In our example, the property name that is provided in the URI can be “Name”, “Description” or “ID”
+So we have to retrieve the property name from the URI.</p>
+<div class="codehilite"><pre><span class="n">Expression</span> <span class="n">expression</span> <span class="o">=</span> <span class="n">orderByItem</span><span class="o">.</span><span class="na">getExpression</span><span class="o">();</span>
+<span class="k">if</span><span class="o">(</span><span class="n">expression</span> <span class="k">instanceof</span> <span class="n">Member</span><span class="o">){</span>
+    <span class="n">UriInfoResource</span> <span class="n">resourcePath</span> <span class="o">=</span> <span class="o">((</span><span class="n">Member</span><span class="o">)</span><span class="n">expression</span><span class="o">).</span><span class="na">getResourcePath</span><span class="o">();</span>
+    <span class="n">UriResource</span> <span class="n">uriResource</span> <span class="o">=</span> <span class="n">resourcePath</span><span class="o">.</span><span class="na">getUriResourceParts</span><span class="o">().</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
+    <span class="k">if</span> <span class="o">(</span><span class="n">uriResource</span> <span class="k">instanceof</span> <span class="n">UriResourcePrimitiveProperty</span><span class="o">)</span> <span class="o">{</span>
+       <span class="n">EdmProperty</span> <span class="n">edmProperty</span> <span class="o">=</span> <span class="o">((</span><span class="n">UriResourcePrimitiveProperty</span><span class="o">)</span><span class="n">uriResource</span><span class="o">).</span><span class="na">getProperty</span><span class="o">();</span>
+       <span class="kd">final</span> <span class="n">String</span> <span class="n">sortPropertyName</span> <span class="o">=</span> <span class="n">edmProperty</span><span class="o">.</span><span class="na">getName</span><span class="o">();</span>
+</pre></div>
+
+
+<p><strong>4. Modify the EntityCollection</strong></p>
+<p>The remaining work is to do the sorting.
+We have a list of entities that has to be sorted, therefore we create a java.util.Comparator for Entity:</p>
+<div class="codehilite"><pre><span class="n">Collections</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="n">entityList</span><span class="o">,</span> <span class="k">new</span> <span class="n">Comparator</span><span class="o">&lt;</span><span class="n">Entity</span><span class="o">&gt;()</span> <span class="o">{</span>
+</pre></div>
+
+
+<p>In the compare method, we extract the required property from the entity.
+The required property is the one that we retrieved from the URI.
+In our sample, the properties can be of type String or Integer, therefore we have to distinguish these 2 cases.
+The actual work of comparing can then be delegated to the String and Integer classes.</p>
+<div class="codehilite"><pre><span class="k">if</span><span class="o">(</span><span class="n">sortPropertyName</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="s">&quot;ID&quot;</span><span class="o">)){</span>
+    <span class="n">Integer</span> <span class="n">integer1</span> <span class="o">=</span> <span class="o">(</span><span class="n">Integer</span><span class="o">)</span> <span class="n">entity1</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="n">sortPropertyName</span><span class="o">).</span><span class="na">getValue</span><span class="o">();</span>
+    <span class="n">Integer</span> <span class="n">integer2</span> <span class="o">=</span> <span class="o">(</span><span class="n">Integer</span><span class="o">)</span> <span class="n">entity2</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="n">sortPropertyName</span><span class="o">).</span><span class="na">getValue</span><span class="o">();</span>
+    <span class="n">compareResult</span> <span class="o">=</span> <span class="n">integer1</span><span class="o">.</span><span class="na">compareTo</span><span class="o">(</span><span class="n">integer2</span><span class="o">);</span>
+<span class="o">}</span><span class="k">else</span><span class="o">{</span>
+    <span class="n">String</span> <span class="n">propertyValue1</span> <span class="o">=</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">entity1</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="n">sortPropertyName</span><span class="o">).</span><span class="na">getValue</span><span class="o">();</span>
+    <span class="n">String</span> <span class="n">propertyValue2</span> <span class="o">=</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">entity2</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="n">sortPropertyName</span><span class="o">).</span><span class="na">getValue</span><span class="o">();</span>
+    <span class="n">compareResult</span> <span class="o">=</span> <span class="n">propertyValue1</span><span class="o">.</span><span class="na">compareTo</span><span class="o">(</span><span class="n">propertyValue2</span><span class="o">);</span>
+<span class="o">}</span>
+</pre></div>
+
+
+<p>After the sorting is done, we still have to consider, if the required order is ascending or descending.
+So we have to retrieve that information from the OrderByItem and then we can simply reverse the current order accordingly:</p>
+<div class="codehilite"><pre><span class="k">if</span><span class="o">(</span><span class="n">orderByItem</span><span class="o">.</span><span class="na">isDescending</span><span class="o">()){</span>
+    <span class="k">return</span> <span class="o">-</span> <span class="n">compareResult</span><span class="o">;</span> <span class="c1">// just convert the result to negative value to change the order</span>
+<span class="o">}</span>
+</pre></div>
+
+
+<p>The full implementation of the readEntityCollection() method:</p>
+<div class="codehilite"><pre><span class="kd">public</span> <span class="kt">void</span> <span class="nf">readEntityCollection</span><span class="o">(</span><span class="n">ODataRequest</span> <span class="n">request</span><span class="o">,</span> <span class="n">ODataResponse</span> <span class="n">response</span><span class="o">,</span> <span class="n">UriInfo</span> <span class="n">uriInfo</span><span class="o">,</span> <span class="n">ContentType</span> <span class="n">responseFormat</span><span class="o">)</span> 
+     <span class="kd">throws</span> <span class="n">ODataApplicationException</span><span class="o">,</span> <span class="n">SerializerException</span> <span class="o">{</span>
+
+    <span class="c1">// 1st retrieve the requested EntitySet from the uriInfo </span>
+    <span class="n">List</span><span class="o">&lt;</span><span class="n">UriResource</span><span class="o">&gt;</span> <span class="n">resourcePaths</span> <span class="o">=</span> <span class="n">uriInfo</span><span class="o">.</span><span class="na">getUriResourceParts</span><span class="o">();</span>
+    <span class="n">UriResourceEntitySet</span> <span class="n">uriResourceEntitySet</span> <span class="o">=</span> <span class="o">(</span><span class="n">UriResourceEntitySet</span><span class="o">)</span> <span class="n">resourcePaths</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span> 
+    <span class="n">EdmEntitySet</span> <span class="n">edmEntitySet</span> <span class="o">=</span> <span class="n">uriResourceEntitySet</span><span class="o">.</span><span class="na">getEntitySet</span><span class="o">();</span>
+
+    <span class="c1">// 2nd: fetch the data from backend </span>
+    <span class="n">EntityCollection</span> <span class="n">entityCollection</span> <span class="o">=</span> <span class="n">storage</span><span class="o">.</span><span class="na">readEntitySetData</span><span class="o">(</span><span class="n">edmEntitySet</span><span class="o">);</span>
+    <span class="n">List</span><span class="o">&lt;</span><span class="n">Entity</span><span class="o">&gt;</span> <span class="n">entityList</span> <span class="o">=</span> <span class="n">entityCollection</span><span class="o">.</span><span class="na">getEntities</span><span class="o">();</span>
+
+    <span class="c1">// 3rd apply $orderby</span>
+    <span class="n">OrderByOption</span> <span class="n">orderByOption</span> <span class="o">=</span> <span class="n">uriInfo</span><span class="o">.</span><span class="na">getOrderByOption</span><span class="o">();</span>
+    <span class="k">if</span> <span class="o">(</span><span class="n">orderByOption</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
+        <span class="n">List</span><span class="o">&lt;</span><span class="n">OrderByItem</span><span class="o">&gt;</span> <span class="n">orderItemList</span> <span class="o">=</span> <span class="n">orderByOption</span><span class="o">.</span><span class="na">getOrders</span><span class="o">();</span>
+        <span class="kd">final</span> <span class="n">OrderByItem</span> <span class="n">orderByItem</span> <span class="o">=</span> <span class="n">orderItemList</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span> <span class="c1">// we support only one</span>
+        <span class="n">Expression</span> <span class="n">expression</span> <span class="o">=</span> <span class="n">orderByItem</span><span class="o">.</span><span class="na">getExpression</span><span class="o">();</span>
+        <span class="k">if</span><span class="o">(</span><span class="n">expression</span> <span class="k">instanceof</span> <span class="n">Member</span><span class="o">){</span>
+            <span class="n">UriInfoResource</span> <span class="n">resourcePath</span> <span class="o">=</span> <span class="o">((</span><span class="n">Member</span><span class="o">)</span><span class="n">expression</span><span class="o">).</span><span class="na">getResourcePath</span><span class="o">();</span>
+            <span class="n">UriResource</span> <span class="n">uriResource</span> <span class="o">=</span> <span class="n">resourcePath</span><span class="o">.</span><span class="na">getUriResourceParts</span><span class="o">().</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
+            <span class="k">if</span> <span class="o">(</span><span class="n">uriResource</span> <span class="k">instanceof</span> <span class="n">UriResourcePrimitiveProperty</span><span class="o">)</span> <span class="o">{</span>
+                <span class="n">EdmProperty</span> <span class="n">edmProperty</span> <span class="o">=</span> <span class="o">((</span><span class="n">UriResourcePrimitiveProperty</span><span class="o">)</span><span class="n">uriResource</span><span class="o">).</span><span class="na">getProperty</span><span class="o">();</span>
+                <span class="kd">final</span> <span class="n">String</span> <span class="n">sortPropertyName</span> <span class="o">=</span> <span class="n">edmProperty</span><span class="o">.</span><span class="na">getName</span><span class="o">();</span>
+
+                <span class="c1">// do the sorting for the list of entities  </span>
+                <span class="n">Collections</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="n">entityList</span><span class="o">,</span> <span class="k">new</span> <span class="n">Comparator</span><span class="o">&lt;</span><span class="n">Entity</span><span class="o">&gt;()</span> <span class="o">{</span>
+
+                    <span class="c1">// delegate the sorting to native sorter of Integer and String</span>
+                    <span class="kd">public</span> <span class="kt">int</span> <span class="nf">compare</span><span class="o">(</span><span class="n">Entity</span> <span class="n">entity1</span><span class="o">,</span> <span class="n">Entity</span> <span class="n">entity2</span><span class="o">)</span> <span class="o">{</span>
+                        <span class="kt">int</span> <span class="n">compareResult</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
+
+                        <span class="k">if</span><span class="o">(</span><span class="n">sortPropertyName</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="s">&quot;ID&quot;</span><span class="o">)){</span>
+                            <span class="n">Integer</span> <span class="n">integer1</span> <span class="o">=</span> <span class="o">(</span><span class="n">Integer</span><span class="o">)</span> <span class="n">entity1</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="n">sortPropertyName</span><span class="o">).</span><span class="na">getValue</span><span class="o">();</span>
+                            <span class="n">Integer</span> <span class="n">integer2</span> <span class="o">=</span> <span class="o">(</span><span class="n">Integer</span><span class="o">)</span> <span class="n">entity2</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="n">sortPropertyName</span><span class="o">).</span><span class="na">getValue</span><span class="o">();</span>
+
+                            <span class="n">compareResult</span> <span class="o">=</span> <span class="n">integer1</span><span class="o">.</span><span class="na">compareTo</span><span class="o">(</span><span class="n">integer2</span><span class="o">);</span>
+                        <span class="o">}</span><span class="k">else</span><span class="o">{</span>
+                            <span class="n">String</span> <span class="n">propertyValue1</span> <span class="o">=</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">entity1</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="n">sortPropertyName</span><span class="o">).</span><span class="na">getValue</span><span class="o">();</span>
+                            <span class="n">String</span> <span class="n">propertyValue2</span> <span class="o">=</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">entity2</span><span class="o">.</span><span class="na">getProperty</span><span class="o">(</span><span class="n">sortPropertyName</span><span class="o">).</span><span class="na">getValue</span><span class="o">();</span>
+
+                            <span class="n">compareResult</span> <span class="o">=</span> <span class="n">propertyValue1</span><span class="o">.</span><span class="na">compareTo</span><span class="o">(</span><span class="n">propertyValue2</span><span class="o">);</span>
+                        <span class="o">}</span>
+
+                        <span class="c1">// if &#39;desc&#39; is specified in the URI, change the order </span>
+                        <span class="k">if</span><span class="o">(</span><span class="n">orderByItem</span><span class="o">.</span><span class="na">isDescending</span><span class="o">()){</span>
+                            <span class="k">return</span> <span class="o">-</span> <span class="n">compareResult</span><span class="o">;</span> <span class="c1">// just reverse order </span>
+                        <span class="o">}</span>
+
+                        <span class="k">return</span> <span class="n">compareResult</span><span class="o">;</span>
+                    <span class="o">}</span>
+                <span class="o">});</span>
+            <span class="o">}</span>
+        <span class="o">}</span>
+    <span class="o">}</span>
+
+
+    <span class="c1">// 4th: create a serializer based on the requested format (json)</span>
+    <span class="n">ODataFormat</span> <span class="n">format</span> <span class="o">=</span> <span class="n">ODataFormat</span><span class="o">.</span><span class="na">fromContentType</span><span class="o">(</span><span class="n">responseFormat</span><span class="o">);</span>
+    <span class="n">ODataSerializer</span> <span class="n">serializer</span> <span class="o">=</span> <span class="n">odata</span><span class="o">.</span><span class="na">createSerializer</span><span class="o">(</span><span class="n">format</span><span class="o">);</span>
+
+    <span class="c1">// and serialize the content: transform from the EntitySet object to InputStream</span>
+    <span class="n">EdmEntityType</span> <span class="n">edmEntityType</span> <span class="o">=</span> <span class="n">edmEntitySet</span><span class="o">.</span><span class="na">getEntityType</span><span class="o">();</span>
+    <span class="n">ContextURL</span> <span class="n">contextUrl</span> <span class="o">=</span> <span class="n">ContextURL</span><span class="o">.</span><span class="na">with</span><span class="o">().</span><span class="na">entitySet</span><span class="o">(</span><span class="n">edmEntitySet</span><span class="o">).</span><span class="na">build</span><span class="o">();</span>
+
+    <span class="n">EntityCollectionSerializerOptions</span> <span class="n">opts</span> <span class="o">=</span> <span class="n">EntityCollectionSerializerOptions</span><span class="o">.</span><span class="na">with</span><span class="o">().</span><span class="na">contextURL</span><span class="o">(</span><span class="n">contextUrl</span><span class="o">).</span><span class="na">build</span><span class="o">();</span>
+    <span class="n">SerializerResult</span> <span class="n">serializerResult</span> <span class="o">=</span> <span class="n">serializer</span><span class="o">.</span><span class="na">entityCollection</span><span class="o">(</span><span class="n">serviceMetadata</span><span class="o">,</span> <span class="n">edmEntityType</span><span class="o">,</span> <span class="n">entityCollection</span><span class="o">,</span> <span class="n">opts</span><span class="o">);</span>
+    <span class="n">InputStream</span> <span class="n">serializedContent</span> <span class="o">=</span> <span class="n">serializerResult</span><span class="o">.</span><span class="na">getContent</span><span class="o">();</span>
+
+    <span class="c1">// 5th: configure the response object: set the body, headers and status code</span>
+    <span class="n">response</span><span class="o">.</span><span class="na">setContent</span><span class="o">(</span><span class="n">serializedContent</span><span class="o">);</span>
+    <span class="n">response</span><span class="o">.</span><span class="na">setStatusCode</span><span class="o">(</span><span class="n">HttpStatusCode</span><span class="o">.</span><span class="na">OK</span><span class="o">.</span><span class="na">getStatusCode</span><span class="o">());</span>
+    <span class="n">response</span><span class="o">.</span><span class="na">setHeader</span><span class="o">(</span><span class="n">HttpHeader</span><span class="o">.</span><span class="na">CONTENT_TYPE</span><span class="o">,</span> <span class="n">responseFormat</span><span class="o">.</span><span class="na">toContentTypeString</span><span class="o">());</span>
+<span class="o">}</span>
+</pre></div>
+
+
+<p><strong>4. Run the implemented service</strong></p>
+<p>After building and deploying your service to your server, you can try the following URLs:</p>
+<ul>
+<li>The “normal” payload without query option  <a href="http://localhost:8080/DemoService/DemoService.svc/Products">http://localhost:8080/DemoService/DemoService.svc/Products</a></li>
+<li>Sort by Name ascending   <a href="http://localhost:8080/DemoService/DemoService.svc/Products?$orderby=Name">http://localhost:8080/DemoService/DemoService.svc/Products?$orderby=Name</a></li>
+<li>Sort by Name descending   <a href="http://localhost:8080/DemoService/DemoService.svc/Products?$orderby=Name desc">http://localhost:8080/DemoService/DemoService.svc/Products?$orderby=Name desc</a></li>
+<li>Sort by Description ascending  <a href="http://localhost:8080/DemoService/DemoService.svc/Products?$orderby=Description">http://localhost:8080/DemoService/DemoService.svc/Products?$orderby=Description</a></li>
+<li>Sort by Description descending  <a href="http://localhost:8080/DemoService/DemoService.svc/Products?$orderby=Description desc">http://localhost:8080/DemoService/DemoService.svc/Products?$orderby=Description desc</a></li>
+</ul>
+<h1 id="5-summary">5. Summary<a class="headerlink" href="#5-summary" title="Permanent link">&para;</a></h1>
+<p>In this tutorial we have learned how to implement a simple $orderby 
+We’ve decided to not go for the advanced way of implementing $orderby, which would have been using an ExpressionVisitor, because that is treated in the $filter implementation.</p>
+<h1 id="6-links">6. Links<a class="headerlink" href="#6-links" title="Permanent link">&para;</a></h1>
+<h3 id="tutorials">Tutorials<a class="headerlink" href="#tutorials" title="Permanent link">&para;</a></h3>
+<ul>
+<li>Tutorial OData V4 service part 1: <a href="/doc/odata4/tutorials/read/tutorial_read.html">Read Entity Collection</a> | <a href="http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_Read.zip">sample project</a> (<a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Read.zip.md5">md5</a>, <a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Read.zip.sha512">sha512</a>, <a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Read.zip.asc">pgp</a>).</li>
+<li>Tutorial OData V4 service part 2: <a href="/doc/odata4/tutorials/readep/tutorial_readep.html">Read Entity, Read Property</a> | <a href="http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip">sample project zip</a> (<a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip.md5">md5</a>, <a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip.sha512">sha512</a>, <a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_ReadEp.zip.asc">pgp</a>)  </li>
+<li>Tutorial OData V4 service part 3: <a href="/doc/odata4/tutorials/write/tutorial_write.html">Write (Create, Update, Delete Entity)</a> | <a href="http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_Write.zip">sample project zip</a> (<a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Write.zip.md5">md5</a>, <a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Write.zip.sha512">sha512</a>, <a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Write.zip.asc">pgp</a>)  </li>
+<li>Tutorial OData V4 service, part 4: <a href="/doc/odata4/tutorials/navigation/tutorial_navigation.html">Navigation</a> | <a href="http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_Navigation.zip">sample project zip</a> (<a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Navigation.zip.md5">md5</a>, <a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Navigation.zip.sha512">sha512</a>, <a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_Navigation.zip.asc">pgp</a>)</li>
+<li>Tutorial OData V4 service, part 5.1: <a href="/doc/odata4/tutorials/sqo_tcs/tutorial_sqo_tcs.html">System Query Options $top, $skip, $count (this page)</a> | <a href="http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_tcs.zip">sample project zip</a> (<a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_tcs.zip.md5">md5</a>, <a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_tcs.zip.sha512">sha512</a>, <a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_tcs.zip.asc">pgp</a>)  </li>
+<li>Tutorial OData V4 service, part 5.2: <a href="/doc/odata4/tutorials/sqo_es/tutorial_sqo_es.html">System Query Options $select, $expand</a> | <a href="http://www.apache.org/dyn/closer.cgi/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_es.zip">sample project zip</a> (<a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_es.zip.md5">md5</a>, <a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_es.zip.sha512">sha512</a>, <a href="https://dist.apache.org/repos/dist/release/olingo/odata4/Tutorials/DemoService_Tutorial_sqo_es.zip.asc">pgp</a>)  </li>
+<li>Tutorial OData V4 service, part 5.3: System Query Options $orderby (this page)</li>
+<li>Tutorial OData V4 service, part 5.4: <a href="/doc/odata4/tutorials/sqo_f/tutorial_sqo_f.html">System Query Options $filter</a></li>
+</ul>
+<p>OData specification: <a href="http://odata.org/">http://odata.org/</a> <br />
+Olingo Javadoc: <a href="http://olingo.apache.org/javadoc/odata4/index.html">http://olingo.apache.org/javadoc/odata4/index.html</a></p><div align="center">
+<p>Copyright © 2013-2015, The Apache Software Foundation<br>
+				                Apache Olingo, Olingo, Apache, the Apache feather, and
+				the Apache Olingo project logo are trademarks of the Apache Software
+				Foundation.</p>
+        <small><a href="/doc/odata2/privacy.html">Privacy</a></small>
+      </div>
+    </div><!-- /container -->
+    <!-- Bootstrap core JavaScript
+    ================================================== -->
+    <!-- Placed at the end of the document so the pages load faster -->
+    <script src="/js/jquery.js" type="text/javascript">
+</script>
+	  <script src="/js/bootstrap.js" type="text/javascript">
+	  <script src="/js/offcanvas.js" type="text/javascript">
+</script>
+        <!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
+        <script>
+            (function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
+            function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
+            e=o.createElement(i);r=o.getElementsByTagName(i)[0];
+            e.src='//www.google-analytics.com/analytics.js';
+            r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
+            ga('create','UA-44963757-1');ga('send','pageview');
+        </script>
+  </body>
+</html>