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 2013/09/26 06:11:29 UTC

svn commit: r879923 - in /websites/staging/olingo/trunk/content: ./ doc/tutorials/read_expand.html

Author: buildbot
Date: Thu Sep 26 04:11:29 2013
New Revision: 879923

Log:
Staging update by buildbot for olingo

Modified:
    websites/staging/olingo/trunk/content/   (props changed)
    websites/staging/olingo/trunk/content/doc/tutorials/read_expand.html

Propchange: websites/staging/olingo/trunk/content/
------------------------------------------------------------------------------
--- cms:source-revision (original)
+++ cms:source-revision Thu Sep 26 04:11:29 2013
@@ -1 +1 @@
-1526091
+1526369

Modified: websites/staging/olingo/trunk/content/doc/tutorials/read_expand.html
==============================================================================
--- websites/staging/olingo/trunk/content/doc/tutorials/read_expand.html (original)
+++ websites/staging/olingo/trunk/content/doc/tutorials/read_expand.html Thu Sep 26 04:11:29 2013
@@ -72,6 +72,213 @@
             <h1 id="read-scenario-read-with-expand">Read Scenario - Read with <code>$expand</code></h1>
 <hr />
 <h2 id="how-to-guide-extend-basic-read-scenario-with-support-for-expand">How To Guide - Extend basic read scenario with support for <code>$expand</code></h2>
+<p>This How To Guide shows how to extend the basic read scenario with support for the $expand system query option.
+It shows how to call the <code>EntityProvider.writeEntry(...)</code> and <code>EntityProvider.writeEntrySet(...)</code> methods with the necessary <code>EntityProviderWriteProperties</code> set and how to implement the necessary <code>OnWriteEntryContent OnWriteFeedContent</code> callbacks.</p>
+<h2 id="prerequisites">Prerequisites</h2>
+<p>Setup of <a href="basicread">Basic Read Scenario</a></p>
+<h2 id="shortcut">Shortcut</h2>
+<p>If you like to directly experiment with the results of the extented basic read scenario, you can use this shortcut: </p>
+<ul>
+<li>Download and unzip <a href="apache-olingo-tutorial-adv_read_expand">Olingo Tutorial 'Basic Read with $expand extension' Project</a> to your local drive </li>
+<li>Start the command line tool and execute the following command in the folder <em>olingo.odata2.sample</em> <ul>
+<li><code>mvn eclipse:eclipse clean install</code> </li>
+</ul>
+</li>
+<li>Go into Eclipse and import the project into your workspace by... <ul>
+<li>Menue <em>File -&gt; Import</em>... </li>
+<li><em>Existing projects into workspace</em>, then choose the <em>olingo.odata2.sample</em> folder </li>
+</ul>
+</li>
+<li>Select both projects <em>olingo.odata2.sample.service</em> and <em>olingo.odata2.sample.web</em> and press <em>Finish</em>. </li>
+</ul>
+<h2 id="set-up-your-development-project">Set Up your development project</h2>
+<p>If <strong><em>Basic Read Scenario</em></strong> is already set up nothing additional is to do. Otherwise please follow the Setup section of the <strong><em>Basic Read Scenario</em></strong>.</p>
+<p><strong>[links: tbd]</strong></p>
+<h2 id="extend-basic-read-scenario">Extend Basic Read Scenario</h2>
+<p>The steps to extend the basic read with $expand support for the Car and Manufacturer entities (not entity sets) are to provide the expanded data via ODataCallbacks and register these for the corresponding navigation properties. </p>
+<h3 id="implement-onwriteentrycontent-and-onwritefeedcontent-callbacks">Implement OnWriteEntryContent and OnWriteFeedContent callbacks</h3>
+<p>Implementation for <code>$expand</code> for a single entry
+To support <code>$expand</code> for a single entry the interface <code>org.apache.olingo.odata2.api.ep.callback.OnWriteEntryContent</code> must be implemented. This provides the method <code>WriteEntryCallbackResult retrieveEntryResult(WriteEntryCallbackContext context) throws ODataApplicationException;</code> which is called during processing from the <code>EntityProvider</code> to receive the necessary data which than is inlined in the response.</p>
+<p>In our sample we create a class <code>MyCallback</code> which implements <code>org.apache.olingo.odata2.api.ep.callback.OnWriteEntryContent</code> in following way:</p>
+<h4 id="sample-code">Sample Code</h4>
+<div class="codehilite"><pre><span class="p">@</span><span class="n">Override</span>
+<span class="n">public</span> <span class="n">WriteEntryCallbackResult</span> <span class="n">retrieveEntryResult</span><span class="p">(</span><span class="n">WriteEntryCallbackContext</span> <span class="n">context</span><span class="p">)</span> <span class="n">throws</span> <span class="n">ODataApplicationException</span> <span class="p">{</span>
+<span class="n">WriteEntryCallbackResult</span> <span class="n">result</span> <span class="p">=</span> <span class="n">new</span> <span class="n">WriteEntryCallbackResult</span><span class="p">();</span>
+
+  <span class="k">try</span> <span class="p">{</span>
+    <span class="k">if</span> <span class="p">(</span><span class="n">isNavigationFromTo</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">ENTITY_SET_NAME_CARS</span><span class="p">,</span> <span class="n">ENTITY_NAME_MANUFACTURER</span><span class="p">))</span> <span class="p">{</span>
+    <span class="n">EntityProviderWriteProperties</span> <span class="n">inlineProperties</span> <span class="p">=</span> <span class="n">EntityProviderWriteProperties</span><span class="p">.</span><span class="n">serviceRoot</span><span class="p">(</span><span class="n">serviceRoot</span><span class="p">)</span>
+        <span class="p">.</span><span class="n">expandSelectTree</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">getCurrentExpandSelectTreeNode</span><span class="p">())</span>
+        <span class="p">.</span><span class="n">build</span><span class="p">();</span>
+
+      <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">Object</span><span class="o">&gt;</span> <span class="n">keys</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="n">extractKeyFromEntryData</span><span class="p">();</span>
+      <span class="n">Integer</span> <span class="n">carId</span> <span class="p">=</span> <span class="p">(</span><span class="n">Integer</span><span class="p">)</span> <span class="n">keys</span><span class="p">.</span><span class="n">get</span><span class="p">(</span>&quot;<span class="n">Id</span>&quot;<span class="p">);</span>
+      <span class="n">result</span><span class="p">.</span><span class="n">setEntryData</span><span class="p">(</span><span class="n">dataStore</span><span class="p">.</span><span class="n">getManufacturerFor</span><span class="p">(</span><span class="n">carId</span><span class="p">));</span>
+      <span class="n">result</span><span class="p">.</span><span class="n">setInlineProperties</span><span class="p">(</span><span class="n">inlineProperties</span><span class="p">);</span>
+    <span class="p">}</span>
+  <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="n">EdmException</span> <span class="n">e</span><span class="p">)</span> <span class="p">{</span>
+  <span class="o">//</span> <span class="n">TODO</span><span class="p">:</span> <span class="n">should</span> <span class="n">be</span> <span class="n">handled</span> <span class="n">and</span> <span class="n">not</span> <span class="n">only</span> <span class="n">logged</span>
+  <span class="n">LOG</span><span class="p">.</span><span class="n">error</span><span class="p">(</span>&quot;<span class="n">Error</span> <span class="n">in</span> $<span class="n">expand</span> <span class="n">handling</span><span class="p">.</span>&quot;<span class="p">,</span> <span class="n">e</span><span class="p">);</span>
+  <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="n">EntityProviderException</span> <span class="n">e</span><span class="p">)</span> <span class="p">{</span>
+  <span class="o">//</span> <span class="n">TODO</span><span class="p">:</span> <span class="n">should</span> <span class="n">be</span> <span class="n">handled</span> <span class="n">and</span> <span class="n">not</span> <span class="n">only</span> <span class="n">logged</span>
+  <span class="n">LOG</span><span class="p">.</span><span class="n">error</span><span class="p">(</span>&quot;<span class="n">Error</span> <span class="n">in</span> $<span class="n">expand</span> <span class="n">handling</span><span class="p">.</span>&quot;<span class="p">,</span> <span class="n">e</span><span class="p">);</span>
+  <span class="p">}</span>
+
+  <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>Within this method we first check if the source entity and navigation property are correct for our case (via the method <code>isNavigationFromTo(...):boolean)</code>, then we create the <code>EntityProviderWriteProperties</code> with the new (current) <code>ExpandSelectTreeNode</code>, receive the data from our <code>DataStore</code> and put all into the result which then will be further processed by the <code>EntityProvider</code>.</p>
+<h3 id="implementation-for-expand-for-an-entity-set">Implementation for $expand for an entity set</h3>
+<p>To support <code>$expand</code> for a feed of entries (entity set) the interface <code>org.apache.olingo.odata2.api.ep.callback.OnWriteFeedContent</code> must be implemented. These provides the method <code>WriteFeedCallbackResult retrieveFeedResult(WriteFeedCallbackContext context) throws ODataApplicationException;</code> which is called during processing from the <code>EntityProvider</code> to receive the necessary data which than is inlined in the response.</p>
+<p>It is possible to create an additional callback class but for convenience we expand our already created callback (<code>MyCallback</code>) to implement <code>org.apache.olingo.odata2.api.ep.callback.OnWriteFeedContent</code> and provide the method implementation in following way:</p>
+<h4 id="sample-code_1">Sample Code</h4>
+<div class="codehilite"><pre><span class="p">@</span><span class="n">Override</span>
+<span class="n">public</span> <span class="n">WriteFeedCallbackResult</span> <span class="n">retrieveFeedResult</span><span class="p">(</span><span class="n">WriteFeedCallbackContext</span> <span class="n">context</span><span class="p">)</span> <span class="n">throws</span> <span class="n">ODataApplicationException</span> <span class="p">{</span>
+<span class="n">WriteFeedCallbackResult</span> <span class="n">result</span> <span class="p">=</span> <span class="n">new</span> <span class="n">WriteFeedCallbackResult</span><span class="p">();</span>
+  <span class="k">try</span> <span class="p">{</span>
+    <span class="k">if</span><span class="p">(</span><span class="n">isNavigationFromTo</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">ENTITY_SET_NAME_MANUFACTURERS</span><span class="p">,</span> <span class="n">ENTITY_SET_NAME_CARS</span><span class="p">))</span> <span class="p">{</span>
+    <span class="n">EntityProviderWriteProperties</span> <span class="n">inlineProperties</span> <span class="p">=</span> <span class="n">EntityProviderWriteProperties</span><span class="p">.</span><span class="n">serviceRoot</span><span class="p">(</span><span class="n">serviceRoot</span><span class="p">)</span>
+        <span class="p">.</span><span class="n">expandSelectTree</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">getCurrentExpandSelectTreeNode</span><span class="p">())</span>
+        <span class="p">.</span><span class="n">selfLink</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">getSelfLink</span><span class="p">())</span>
+        <span class="p">.</span><span class="n">build</span><span class="p">();</span>
+
+      <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">Object</span><span class="o">&gt;</span> <span class="n">keys</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="n">extractKeyFromEntryData</span><span class="p">();</span>
+      <span class="n">Integer</span> <span class="n">manufacturerId</span> <span class="p">=</span> <span class="p">(</span><span class="n">Integer</span><span class="p">)</span> <span class="n">keys</span><span class="p">.</span><span class="n">get</span><span class="p">(</span>&quot;<span class="n">Id</span>&quot;<span class="p">);</span>
+      <span class="n">result</span><span class="p">.</span><span class="n">setFeedData</span><span class="p">(</span><span class="n">dataStore</span><span class="p">.</span><span class="n">getCarsFor</span><span class="p">(</span><span class="n">manufacturerId</span><span class="p">));</span>
+      <span class="n">result</span><span class="p">.</span><span class="n">setInlineProperties</span><span class="p">(</span><span class="n">inlineProperties</span><span class="p">);</span>
+    <span class="p">}</span>
+  <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="n">EdmException</span> <span class="n">e</span><span class="p">)</span> <span class="p">{</span>
+  <span class="o">//</span> <span class="n">TODO</span><span class="p">:</span> <span class="n">should</span> <span class="n">be</span> <span class="n">handled</span> <span class="n">and</span> <span class="n">not</span> <span class="n">only</span> <span class="n">logged</span>
+  <span class="n">LOG</span><span class="p">.</span><span class="n">error</span><span class="p">(</span>&quot;<span class="n">Error</span> <span class="n">in</span> $<span class="n">expand</span> <span class="n">handling</span><span class="p">.</span>&quot;<span class="p">,</span> <span class="n">e</span><span class="p">);</span>
+  <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="n">EntityProviderException</span> <span class="n">e</span><span class="p">)</span> <span class="p">{</span>
+  <span class="o">//</span> <span class="n">TODO</span><span class="p">:</span> <span class="n">should</span> <span class="n">be</span> <span class="n">handled</span> <span class="n">and</span> <span class="n">not</span> <span class="n">only</span> <span class="n">logged</span>
+  <span class="n">LOG</span><span class="p">.</span><span class="n">error</span><span class="p">(</span>&quot;<span class="n">Error</span> <span class="n">in</span> $<span class="n">expand</span> <span class="n">handling</span><span class="p">.</span>&quot;<span class="p">,</span> <span class="n">e</span><span class="p">);</span>
+  <span class="p">}</span>
+  <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>Within this method we first check if the source entity and navigation property are correct for our case (via the method <code>isNavigationFromTo(...):boolean)</code>, then we create the <code>EntityProviderWriteProperties</code> with the new (current) <code>ExpandSelectTreeNode</code>, receive the data from our <code>DataStore</code> and put all into the result which then will be further processed by the <code>EntityProvider</code>.</p>
+<p>This example shows that the basic callback logic between <code>OnWriteEntryConten</code>t and <code>OnWriteFeedContent</code> is very similar. Validation of current element (optional), preparing of <code>EntityProviderWriteProperties</code>, receive of data and putting all together into corresponding result object (<code>WriteEntryCallbackResult</code> or <code>WriteFeedCallbackResult</code>).</p>
+<p>To improve code readability the <code>isNavigationFromTo(...):boolean</code> method was also added to the class. The method is used to check if the retrieved request is related to given entity set and navigation:</p>
+<h4 id="sample-code_2">Sample Code</h4>
+<div class="codehilite"><pre><span class="n">private</span> <span class="n">boolean</span> <span class="n">isNavigationFromTo</span><span class="p">(</span><span class="n">WriteCallbackContext</span> <span class="n">context</span><span class="p">,</span> <span class="n">String</span> <span class="n">entitySetName</span><span class="p">,</span> <span class="n">String</span> <span class="n">navigationPropertyName</span><span class="p">)</span> <span class="n">throws</span> <span class="n">EdmException</span> <span class="p">{</span>
+  <span class="k">if</span><span class="p">(</span><span class="n">entitySetName</span> <span class="o">==</span> <span class="n">null</span> <span class="o">||</span> <span class="n">navigationPropertyName</span> <span class="o">==</span> <span class="n">null</span><span class="p">)</span> <span class="p">{</span>
+  <span class="k">return</span> <span class="n">false</span><span class="p">;</span>
+  <span class="p">}</span>
+  <span class="n">EdmEntitySet</span> <span class="n">sourceEntitySet</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="n">getSourceEntitySet</span><span class="p">();</span>
+  <span class="n">EdmNavigationProperty</span> <span class="n">navigationProperty</span> <span class="p">=</span> <span class="n">context</span><span class="p">.</span><span class="n">getNavigationProperty</span><span class="p">();</span>
+  <span class="k">return</span> <span class="n">entitySetName</span><span class="p">.</span><span class="n">equals</span><span class="p">(</span><span class="n">sourceEntitySet</span><span class="p">.</span><span class="n">getName</span><span class="p">())</span> <span class="o">&amp;&amp;</span> <span class="n">navigationPropertyName</span><span class="p">.</span><span class="n">equals</span><span class="p">(</span><span class="n">navigationProperty</span><span class="p">.</span><span class="n">getName</span><span class="p">());</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<h3 id="extend-odatasingleprocessorreadentity">Extend ODataSingleProcessor.readEntity(...)</h3>
+<p>The necessary callbacks (<code>MyCallback</code> class) now has to be registered during the corresponding <code>readEntity(...)</code> call. Therefore we first create a map with the property name as key and the according callback as value. Additional we need to create the <code>ExpandSelectTreeNode</code> based on current element position. Both then have to be set in the <code>EntityProviderWritePropertiesBuilder</code>. </p>
+<p>The following code show the few lines we need for extending the read of a car with its expanded manufacturer.</p>
+<div class="codehilite"><pre><span class="c1">// create and register callback</span>
+<span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">ODataCallback</span><span class="o">&gt;</span> <span class="n">callbacks</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">ODataCallback</span><span class="o">&gt;</span><span class="p">();</span>
+<span class="n">callbacks</span><span class="p">.</span><span class="n">put</span><span class="p">(</span><span class="no">ENTITY_NAME_MANUFACTURER</span><span class="p">,</span> <span class="k">new</span> <span class="n">MyCallback</span><span class="p">(</span><span class="n">dataStore</span><span class="p">,</span> <span class="n">serviceRoot</span><span class="p">));</span>
+<span class="n">ExpandSelectTreeNode</span> <span class="n">expandSelectTreeNode</span> <span class="o">=</span> <span class="n">UriParser</span><span class="p">.</span><span class="n">createExpandSelectTree</span><span class="p">(</span><span class="n">uriInfo</span><span class="p">.</span><span class="n">getSelect</span><span class="p">(),</span> <span class="n">uriInfo</span><span class="p">.</span><span class="n">getExpand</span><span class="p">());</span>
+<span class="n">propertiesBuilder</span><span class="p">.</span><span class="n">expandSelectTree</span><span class="p">(</span><span class="n">expandSelectTreeNode</span><span class="p">).</span><span class="n">callbacks</span><span class="p">(</span><span class="n">callbacks</span><span class="p">);</span>
+</pre></div>
+
+
+<p>The following code show the few lines we need for extending the read of a manufacturer with its expanded cars.</p>
+<div class="codehilite"><pre><span class="c1">// create and register callback</span>
+<span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">ODataCallback</span><span class="o">&gt;</span> <span class="n">callbacks</span> <span class="o">=</span> <span class="k">new</span> <span class="n">HashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">ODataCallback</span><span class="o">&gt;</span><span class="p">();</span>
+<span class="n">callbacks</span><span class="p">.</span><span class="n">put</span><span class="p">(</span><span class="no">ENTITY_SET_NAME_CARS</span><span class="p">,</span> <span class="k">new</span> <span class="n">MyCallback</span><span class="p">(</span><span class="n">dataStore</span><span class="p">,</span> <span class="n">serviceRoot</span><span class="p">));</span>
+<span class="n">ExpandSelectTreeNode</span> <span class="n">expandSelectTreeNode</span> <span class="o">=</span> <span class="n">UriParser</span><span class="p">.</span><span class="n">createExpandSelectTree</span><span class="p">(</span><span class="n">uriInfo</span><span class="p">.</span><span class="n">getSelect</span><span class="p">(),</span> <span class="n">uriInfo</span><span class="p">.</span><span class="n">getExpand</span><span class="p">());</span>
+<span class="n">propertiesBuilder</span><span class="p">.</span><span class="n">expandSelectTree</span><span class="p">(</span><span class="n">expandSelectTreeNode</span><span class="p">).</span><span class="n">callbacks</span><span class="p">(</span><span class="n">callbacks</span><span class="p">);</span>
+</pre></div>
+
+
+<p>The complete <code>readEntity(...)</code> method should now look like:</p>
+<div class="codehilite"><pre><span class="n">public</span> <span class="n">ODataResponse</span> <span class="n">readEntity</span><span class="p">(</span><span class="n">GetEntityUriInfo</span> <span class="n">uriInfo</span><span class="p">,</span> <span class="n">String</span> <span class="n">contentType</span><span class="p">)</span> <span class="n">throws</span> <span class="n">ODataException</span> <span class="p">{</span>
+
+  <span class="k">if</span> <span class="p">(</span><span class="n">uriInfo</span><span class="p">.</span><span class="n">getNavigationSegments</span><span class="p">().</span><span class="nb">size</span><span class="p">()</span> <span class="o">==</span> 0<span class="p">)</span> <span class="p">{</span>
+  <span class="n">EdmEntitySet</span> <span class="n">entitySet</span> <span class="p">=</span> <span class="n">uriInfo</span><span class="p">.</span><span class="n">getStartEntitySet</span><span class="p">();</span>
+
+    <span class="k">if</span> <span class="p">(</span><span class="n">ENTITY_SET_NAME_CARS</span><span class="p">.</span><span class="n">equals</span><span class="p">(</span><span class="n">entitySet</span><span class="p">.</span><span class="n">getName</span><span class="p">()))</span> <span class="p">{</span>
+    <span class="n">int</span> <span class="n">id</span> <span class="p">=</span> <span class="n">getKeyValue</span><span class="p">(</span><span class="n">uriInfo</span><span class="p">.</span><span class="n">getKeyPredicates</span><span class="p">().</span><span class="n">get</span><span class="p">(</span>0<span class="p">));</span>
+    <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">Object</span><span class="o">&gt;</span> <span class="n">data</span> <span class="p">=</span> <span class="n">dataStore</span><span class="p">.</span><span class="n">getCar</span><span class="p">(</span><span class="n">id</span><span class="p">);</span>
+
+      <span class="k">if</span> <span class="p">(</span><span class="n">data</span> !<span class="p">=</span> <span class="n">null</span><span class="p">)</span> <span class="p">{</span>
+      <span class="n">URI</span> <span class="n">serviceRoot</span> <span class="p">=</span> <span class="n">getContext</span><span class="p">().</span><span class="n">getPathInfo</span><span class="p">().</span><span class="n">getServiceRoot</span><span class="p">();</span>
+      <span class="n">ODataEntityProviderPropertiesBuilder</span> <span class="n">propertiesBuilder</span> <span class="p">=</span> <span class="n">EntityProviderWriteProperties</span><span class="p">.</span><span class="n">serviceRoot</span><span class="p">(</span><span class="n">serviceRoot</span><span class="p">);</span>
+
+        <span class="o">//</span> <span class="n">create</span> <span class="n">and</span> <span class="n">register</span> <span class="n">callback</span>
+      <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">ODataCallback</span><span class="o">&gt;</span> <span class="n">callbacks</span> <span class="p">=</span> <span class="n">new</span> <span class="n">HashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">ODataCallback</span><span class="o">&gt;</span><span class="p">();</span>
+      <span class="n">callbacks</span><span class="p">.</span><span class="n">put</span><span class="p">(</span><span class="n">ENTITY_NAME_MANUFACTURER</span><span class="p">,</span> <span class="n">new</span> <span class="n">MyCallback</span><span class="p">(</span><span class="n">dataStore</span><span class="p">,</span> <span class="n">serviceRoot</span><span class="p">));</span>
+      <span class="n">ExpandSelectTreeNode</span> <span class="n">expandSelectTreeNode</span> <span class="p">=</span> <span class="n">UriParser</span><span class="p">.</span><span class="n">createExpandSelectTree</span><span class="p">(</span><span class="n">uriInfo</span><span class="p">.</span><span class="n">getSelect</span><span class="p">(),</span> <span class="n">uriInfo</span><span class="p">.</span><span class="n">getExpand</span><span class="p">());</span>
+        <span class="o">//</span>
+        <span class="n">propertiesBuilder</span><span class="p">.</span><span class="n">expandSelectTree</span><span class="p">(</span><span class="n">expandSelectTreeNode</span><span class="p">).</span><span class="n">callbacks</span><span class="p">(</span><span class="n">callbacks</span><span class="p">);</span>
+
+         <span class="k">return</span> <span class="n">EntityProvider</span><span class="p">.</span><span class="n">writeEntry</span><span class="p">(</span><span class="n">contentType</span><span class="p">,</span> <span class="n">entitySet</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">propertiesBuilder</span><span class="p">.</span><span class="n">build</span><span class="p">());</span>
+      <span class="p">}</span>
+    <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">ENTITY_SET_NAME_MANUFACTURERS</span><span class="p">.</span><span class="n">equals</span><span class="p">(</span><span class="n">entitySet</span><span class="p">.</span><span class="n">getName</span><span class="p">()))</span> <span class="p">{</span>
+      <span class="n">int</span> <span class="n">id</span> <span class="p">=</span> <span class="n">getKeyValue</span><span class="p">(</span><span class="n">uriInfo</span><span class="p">.</span><span class="n">getKeyPredicates</span><span class="p">().</span><span class="n">get</span><span class="p">(</span>0<span class="p">));</span>
+      <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">Object</span><span class="o">&gt;</span> <span class="n">data</span> <span class="p">=</span> <span class="n">dataStore</span><span class="p">.</span><span class="n">getManufacturer</span><span class="p">(</span><span class="n">id</span><span class="p">);</span>
+
+      <span class="k">if</span> <span class="p">(</span><span class="n">data</span> !<span class="p">=</span> <span class="n">null</span><span class="p">)</span> <span class="p">{</span>
+        <span class="n">URI</span> <span class="n">serviceRoot</span> <span class="p">=</span> <span class="n">getContext</span><span class="p">().</span><span class="n">getPathInfo</span><span class="p">().</span><span class="n">getServiceRoot</span><span class="p">();</span>
+        <span class="n">ODataEntityProviderPropertiesBuilder</span> <span class="n">propertiesBuilder</span> <span class="p">=</span> <span class="n">EntityProviderWriteProperties</span><span class="p">.</span><span class="n">serviceRoot</span><span class="p">(</span><span class="n">serviceRoot</span><span class="p">);</span>
+
+        <span class="o">//</span> <span class="n">create</span> <span class="n">and</span> <span class="n">register</span> <span class="n">callback</span>
+        <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">ODataCallback</span><span class="o">&gt;</span> <span class="n">callbacks</span> <span class="p">=</span> <span class="n">new</span> <span class="n">HashMap</span><span class="o">&lt;</span><span class="n">String</span><span class="p">,</span> <span class="n">ODataCallback</span><span class="o">&gt;</span><span class="p">();</span>
+        <span class="n">callbacks</span><span class="p">.</span><span class="n">put</span><span class="p">(</span><span class="n">ENTITY_SET_NAME_CARS</span><span class="p">,</span> <span class="n">new</span> <span class="n">MyCallback</span><span class="p">(</span><span class="n">dataStore</span><span class="p">,</span> <span class="n">serviceRoot</span><span class="p">));</span>
+        <span class="n">ExpandSelectTreeNode</span> <span class="n">expandSelectTreeNode</span> <span class="p">=</span> <span class="n">UriParser</span><span class="p">.</span><span class="n">createExpandSelectTree</span><span class="p">(</span><span class="n">uriInfo</span><span class="p">.</span><span class="n">getSelect</span><span class="p">(),</span> <span class="n">uriInfo</span><span class="p">.</span><span class="n">getExpand</span><span class="p">());</span>
+        <span class="o">//</span>
+        <span class="n">propertiesBuilder</span><span class="p">.</span><span class="n">expandSelectTree</span><span class="p">(</span><span class="n">expandSelectTreeNode</span><span class="p">).</span><span class="n">callbacks</span><span class="p">(</span><span class="n">callbacks</span><span class="p">);</span>
+
+        <span class="k">return</span> <span class="n">EntityProvider</span><span class="p">.</span><span class="n">writeEntry</span><span class="p">(</span><span class="n">contentType</span><span class="p">,</span> <span class="n">entitySet</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">propertiesBuilder</span><span class="p">.</span><span class="n">build</span><span class="p">());</span>
+      <span class="p">}</span>
+    <span class="p">}</span>
+
+    <span class="n">throw</span> <span class="n">new</span> <span class="n">ODataNotFoundException</span><span class="p">(</span><span class="n">ODataNotFoundException</span><span class="p">.</span><span class="n">ENTITY</span><span class="p">);</span>
+
+  <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">uriInfo</span><span class="p">.</span><span class="n">getNavigationSegments</span><span class="p">().</span><span class="nb">size</span><span class="p">()</span> <span class="o">==</span> 1<span class="p">)</span> <span class="p">{</span>
+    <span class="o">//</span><span class="n">navigation</span> <span class="n">first</span> <span class="n">level</span><span class="p">,</span> <span class="n">simplified</span> <span class="n">example</span> <span class="k">for</span> <span class="n">illustration</span> <span class="n">purposes</span> <span class="n">only</span>
+    <span class="n">EdmEntitySet</span> <span class="n">entitySet</span> <span class="p">=</span> <span class="n">uriInfo</span><span class="p">.</span><span class="n">getTargetEntitySet</span><span class="p">();</span>
+    <span class="k">if</span> <span class="p">(</span><span class="n">ENTITY_SET_NAME_MANUFACTURERS</span><span class="p">.</span><span class="n">equals</span><span class="p">(</span><span class="n">entitySet</span><span class="p">.</span><span class="n">getName</span><span class="p">()))</span> <span class="p">{</span>
+      <span class="n">int</span> <span class="n">carKey</span> <span class="p">=</span> <span class="n">getKeyValue</span><span class="p">(</span><span class="n">uriInfo</span><span class="p">.</span><span class="n">getKeyPredicates</span><span class="p">().</span><span class="n">get</span><span class="p">(</span>0<span class="p">));</span>
+      <span class="k">return</span> <span class="n">EntityProvider</span><span class="p">.</span><span class="n">writeEntry</span><span class="p">(</span><span class="n">contentType</span><span class="p">,</span> <span class="n">uriInfo</span><span class="p">.</span><span class="n">getTargetEntitySet</span><span class="p">(),</span> <span class="n">dataStore</span><span class="p">.</span><span class="n">getManufacturer</span><span class="p">(</span><span class="n">carKey</span><span class="p">),</span>   <span class="n">EntityProviderWriteProperties</span><span class="p">.</span><span class="n">serviceRoot</span><span class="p">(</span><span class="n">getContext</span><span class="p">().</span><span class="n">getPathInfo</span><span class="p">().</span><span class="n">getServiceRoot</span><span class="p">()).</span><span class="n">build</span><span class="p">());</span>
+    <span class="p">}</span>
+
+    <span class="n">throw</span> <span class="n">new</span> <span class="n">ODataNotFoundException</span><span class="p">(</span><span class="n">ODataNotFoundException</span><span class="p">.</span><span class="n">ENTITY</span><span class="p">);</span>
+  <span class="p">}</span>
+
+  <span class="n">throw</span> <span class="n">new</span> <span class="n">ODataNotImplementedException</span><span class="p">();</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>Now we can test out <code>$expand</code> extension in the web application.</p>
+<h3 id="deploy-run-and-test-expand">Deploy, run and test $expand</h3>
+<p>Like in the basic read scenario follow these steps:</p>
+<ul>
+<li>Build your project: <code>mvn clean install</code> </li>
+<li>When build finished in Eclipse, run the Web Application via <em>Run As -&gt; Run on Server</em> </li>
+<li>After successful server start and deployment the following uris from the basic read sample work as before: <ul>
+<li>Show the Manufacturers: <a href="http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Manufacturers">http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Manufacturers</a> </li>
+<li>Show one Manufacturer: <a href="http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Manufacturers(1)">http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Manufacturers(1)</a> </li>
+<li>Show the Cars: <a href="http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Cars">http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Cars</a> </li>
+<li>Show one Car: <a href="http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Cars(2)">http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Cars(2)</a> </li>
+<li>Show the related Manufacturer of a Car: <a href="http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Cars(2)/Manufacturer">http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Cars(2)/Manufacturer</a> </li>
+<li>Show the related Cars of a Manufacturer: <a href="http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Manufacturers(1)/Cars">http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Manufacturers(1)/Cars</a> </li>
+</ul>
+</li>
+<li>And in addition we can now expand the car and manufacturer with each other: <ul>
+<li>Show Car with its Manufacturer: <a href="http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Cars(2)?$expand=Manufacturer">http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Cars(2)?$expand=Manufacturer </a></li>
+<li>Show Manufacturer with its Cars: <a href="http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Manufacturers(1)?$expand=Cars">http://localhost:8080/olingo.odata2.sample.cars.web/MyODataSample.svc/Manufacturers(1)?$expand=Cars</a> </li>
+</ul>
+</li>
+</ul>
+<h2 id="further-information">Further Information</h2>
+<p>Next extension step for read scenario are read of <a href="read_mediaresource">Media Resources</a>. </p>