Author: buildbot
Date: Tue May 19 09:20:01 2015
New Revision: 951850
Log:
Staging update by buildbot for olingo
Added:
websites/staging/olingo/trunk/content/doc/odata4/tutorials/write/
websites/staging/olingo/trunk/content/doc/odata4/tutorials/write/tutorial_write.html
Modified:
websites/staging/olingo/trunk/content/ (props changed)
Propchange: websites/staging/olingo/trunk/content/
------------------------------------------------------------------------------
--- cms:source-revision (original)
+++ cms:source-revision Tue May 19 09:20:01 2015
@@ -1 +1 @@
-1680203
+1680207
Added:
websites/staging/olingo/trunk/content/doc/odata4/tutorials/write/tutorial_write.html
==============================================================================
---
websites/staging/olingo/trunk/content/doc/odata4/tutorials/write/tutorial_write.html
(added)
+++
websites/staging/olingo/trunk/content/doc/odata4/tutorials/write/tutorial_write.html
Tue May 19 09:20:01 2015
@@ -0,0 +1,444 @@
+<!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 --><h1 id="how-to-build-an-odata-service-with-olingo-v4">How to build an
OData Service with Olingo V4</h1>
+<h1 id="part-3-write-operations">Part 3: Write operations</h1>
+<h2 id="introduction">Introduction</h2>
+<p>This tutorial guides you through the steps required to write an OData
Service based on the Olingo OData 4.0 Library for Java (based on current
<em>Olingo 4.0.0-beta-03</em> release which can be get via the <a
href="/doc/odata4/download.html">Download-Page</a>).</p>
+<p>In the first two tutorials (<a
href="/doc/odata4/tutorials/read/tutorial_read.html">Read Collection</a> and <a
href="/doc/odata4/tutorials/readep/tutorial_readep.html">Read Entity</a>),
weâve learned how to build a simple OData service that supports read
operations for collection, single entity and property.</p>
+<p>In the present tutorial, will cover the write operations, which means
creating an entity, modifying an existing entity and deleting an existing
entity.</p>
+<p>Note:<br />
+The full implementation of the OData service as described in the present
tutorial can be found in the <a
href="/doc/odata4/tutorials/write/sample/DemoService_Tutorial_Write.zip">attached
zip file</a> (<a
href="/doc/odata4/tutorials/write/sample/DemoService_Tutorial_Write.zip.md5">md5</a>,
<a
href="/doc/odata4/tutorials/write/sample/DemoService_Tutorial_Write.zip.sha512">sha512</a>,
<a
href="/doc/odata4/tutorials/write/sample/DemoService_Tutorial_Write.zip.asc">pgp</a>)
that contains an Eclipse project that can be imported into your Eclipse
workspace.</p>
+<p>Disclaimer:
+Again, in the present tutorial, will focus only on the relevant
implementation, in order to keep the code small and simple.
+The sample code shouldn't be reused for advanced scenarios.</p>
+<hr />
+<h1 id="1-prerequisites">1. Prerequisites</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>
+<hr />
+<h1 id="2-preparation">2. Preparation</h1>
+<p>Follow <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> or as shortcut import the project attached to
<em>Tutorial Part 2</em> into your Eclipse workspace.</p>
+<p>Afterwards do a <em>Deploy and run</em>: it should be working.</p>
+<hr />
+<h1 id="3-implementation">3. Implementation</h1>
+<p>In our sample scenario, we want to create a product, to be added to the
list of available products that we maintain in our database-mock.
+This product that we want to create will have a name and a description that
the user of our service will specify in his HTTP request.
+The Olingo library takes this user request, serializes the request body and
invokes the corresponding method of our processor class.</p>
+<p>In the previous tutorial 2, weâve already implemented the
<code>EntityProcessor</code> interface and registered our class in the servlet,
but we have not written the implementation for the callback methods that are
responsible for the write operations.
+This is what we are going to do in the below sections.</p>
+<h2 id="31-implement-the-createentity-method">3.1. Implement the
createEntity(...) method</h2>
+<p>Open the class
<code>myservice.mynamespace.service.DemoEntityProcessor</code><br />
+Go to the method <code>createEntity(...)</code><br />
+The method body should be empty, otherwise delete any content.</p>
+<p><strong>Now, how to implement the method?</strong><br />
+Basically, we have to do the same that we did in the
<code>readEntity(...)</code> method, but the other way âround.<br />
+In the <code>createEntity(...)</code> method, we have to retrieve the payload
from the request and then write it to our mock-database.<br />
+Furthermore, we have to return the created entity in the response payload.</p>
+<p>Again, we can divide our work into 4 steps:</p>
+<ol>
+<li>Analyze the URI</li>
+<li>Handle data in backend</li>
+<li>Serialize</li>
+<li>Configure the response</li>
+</ol>
+<p><strong>In detail</strong></p>
+<p>We have to keep in mind that -for creation - the URL that is executed in
our example is the following:</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>
+</pre></div>
+
+
+<p>It is executed as POST request and contains a request body which looks as
follows:</p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="nt">"ID"</span><span class="p">:</span><span
class="mi">4</span><span class="p">,</span>
+ <span class="nt">"Name"</span><span class="p">:</span><span
class="s2">"Gamer Mouse"</span><span class="p">,</span>
+ <span class="nt">"Description"</span><span class="p">:</span><span
class="s2">"optical mouse - gamer edition"</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p><strong>Steps</strong></p>
+<ol>
+<li>In the implementation, we have to first retrieve the
<code>EntityCollection</code> and <code>EntityType</code> metadata from the
<code>UriInfo</code> object.</li>
+<li>The next step is to create the data in our backend.<br />
+ For this purpose, we have to retrieve the data from the HTTP request
payload.<br />
+ We get the payload from the <code>ODataRequest</code> instance as
<code>InputStream</code>, which can then be deserialized.
+ Our <code>Storage</code> class is responsible for creating the new product
in the backend.
+ And for returning the newly created instance.<br />
+ The reason is that our OData service has to return the newly created entity
in the response body. </li>
+<li>From now on the procedure is the same like in the
<code>readEntity(...)</code> method</li>
+<li>The only difference is the status code, that has to be set to <strong>201
- created</strong> in case of success</li>
+</ol>
+<p>Please find below the sample code for the <em>createEntity()</em> method</p>
+<div class="codehilite"><pre><span class="kd">public</span> <span
class="kt">void</span> <span class="nf">createEntity</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">requestFormat</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">DeserializerException</span><span class="o">,</span> <span
class="n">SerializerException</span> <span class="o">{</span>
+
+ <span class="c1">// 1. Retrieve the entity type from the URI</span>
+ <span class="n">EdmEntitySet</span> <span class="n">edmEntitySet</span>
<span class="o">=</span> <span class="n">Util</span><span
class="o">.</span><span class="na">getEdmEntitySet</span><span
class="o">(</span><span class="n">uriInfo</span><span class="o">);</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="c1">// 2. create the data in backend</span>
+ <span class="c1">// 2.1. retrieve the payload from the POST request for the
entity to create and deserialize it</span>
+ <span class="n">InputStream</span> <span class="n">requestInputStream</span>
<span class="o">=</span> <span class="n">request</span><span
class="o">.</span><span class="na">getBody</span><span class="o">();</span>
+ <span class="n">ODataFormat</span> <span class="n">requestODataFormat</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">requestFormat</span><span class="o">);</span>
+ <span class="n">ODataDeserializer</span> <span class="n">deserializer</span>
<span class="o">=</span> <span class="k">this</span><span
class="o">.</span><span class="na">odata</span><span class="o">.</span><span
class="na">createDeserializer</span><span class="o">(</span><span
class="n">requestODataFormat</span><span class="o">);</span>
+ <span class="n">DeserializerResult</span> <span class="n">result</span>
<span class="o">=</span> <span class="n">deserializer</span><span
class="o">.</span><span class="na">entity</span><span class="o">(</span><span
class="n">requestInputStream</span><span class="o">,</span> <span
class="n">edmEntityType</span><span class="o">);</span>
+ <span class="n">Entity</span> <span class="n">requestEntity</span> <span
class="o">=</span> <span class="n">result</span><span class="o">.</span><span
class="na">getEntity</span><span class="o">();</span>
+ <span class="c1">// 2.2 do the creation in backend, which returns the newly
created entity</span>
+ <span class="n">Entity</span> <span class="n">createdEntity</span> <span
class="o">=</span> <span class="n">storage</span><span class="o">.</span><span
class="na">createEntityData</span><span class="o">(</span><span
class="n">edmEntitySet</span><span class="o">,</span> <span
class="n">requestEntity</span><span class="o">);</span>
+
+ <span class="c1">// 3. serialize the response (we have to return the created
entity)</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="c1">// expand and select currently not supported</span>
+ <span class="n">EntitySerializerOptions</span> <span
class="n">options</span> <span class="o">=</span> <span
class="n">EntitySerializerOptions</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">ODataFormat</span> <span class="n">oDataFormat</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="k">this</span><span
class="o">.</span><span class="na">odata</span><span class="o">.</span><span
class="na">createSerializer</span><span class="o">(</span><span
class="n">oDataFormat</span><span class="o">);</span>
+ <span class="n">SerializerResult</span> <span
class="n">serializedResponse</span> <span class="o">=</span> <span
class="n">serializer</span><span class="o">.</span><span
class="na">entity</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">createdEntity</span><span class="o">,</span> <span
class="n">options</span><span class="o">);</span>
+
+ <span class="c1">//4. configure the response object</span>
+ <span class="n">response</span><span class="o">.</span><span
class="na">setContent</span><span class="o">(</span><span
class="n">serializedResponse</span><span class="o">.</span><span
class="na">getContent</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">CREATED</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>
+
+
+<h2 id="32-implement-the-updateentity-method">3.2. Implement the
updateEntity(...) method</h2>
+<p>Example URL</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="p">(</span>3<span class="p">)</span>
+</pre></div>
+
+
+<p>Example request body:</p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="nt">"ID"</span><span class="p">:</span><span
class="mi">3</span><span class="p">,</span>
+ <span class="nt">"Name"</span><span class="p">:</span><span
class="s2">"Ergo Screen updated Name"</span><span class="p">,</span>
+ <span class="nt">"Description"</span><span class="p">:</span><span
class="s2">"updated description"</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>The <code>updateEntity(...)</code> method is similar.<br />
+Again, we have to retrieve the payload from the HTTP request and use it for
modifying the data in backend.
+The difference is that case of update operation, the OData service is not
expected to return any response payload. So we can skip the serialize-step and
simply set the HTTP status code to <strong>204 â no content</strong></p>
+<div class="codehilite"><pre><span class="kd">public</span> <span
class="kt">void</span> <span class="nf">updateEntity</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">requestFormat</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">DeserializerException</span><span class="o">,</span> <span
class="n">SerializerException</span> <span class="o">{</span>
+
+ <span class="c1">// 1. Retrieve the entity set which belongs to the
requested entity</span>
+ <span class="n">List</span><span class="o"><</span><span
class="n">UriResource</span><span class="o">></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="c1">// Note: only in our example we can assume that the first
segment is the EntitySet</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="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="c1">// 2. update the data in backend</span>
+ <span class="c1">// 2.1. retrieve the payload from the PUT request for the
entity to be updated</span>
+ <span class="n">InputStream</span> <span class="n">requestInputStream</span>
<span class="o">=</span> <span class="n">request</span><span
class="o">.</span><span class="na">getBody</span><span class="o">();</span>
+ <span class="n">ODataFormat</span> <span class="n">requestODataFormat</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">requestFormat</span><span class="o">);</span>
+ <span class="n">ODataDeserializer</span> <span class="n">deserializer</span>
<span class="o">=</span> <span class="k">this</span><span
class="o">.</span><span class="na">odata</span><span class="o">.</span><span
class="na">createDeserializer</span><span class="o">(</span><span
class="n">requestODataFormat</span><span class="o">);</span>
+ <span class="n">DeserializerResult</span> <span class="n">result</span>
<span class="o">=</span> <span class="n">deserializer</span><span
class="o">.</span><span class="na">entity</span><span class="o">(</span><span
class="n">requestInputStream</span><span class="o">,</span> <span
class="n">edmEntityType</span><span class="o">);</span>
+ <span class="n">Entity</span> <span class="n">requestEntity</span> <span
class="o">=</span> <span class="n">result</span><span class="o">.</span><span
class="na">getEntity</span><span class="o">();</span>
+ <span class="c1">// 2.2 do the modification in backend</span>
+ <span class="n">List</span><span class="o"><</span><span
class="n">UriParameter</span><span class="o">></span> <span
class="n">keyPredicates</span> <span class="o">=</span> <span
class="n">uriResourceEntitySet</span><span class="o">.</span><span
class="na">getKeyPredicates</span><span class="o">();</span>
+ <span class="c1">// Note that this updateEntity()-method is invoked for both
PUT or PATCH operations</span>
+ <span class="n">HttpMethod</span> <span class="n">httpMethod</span> <span
class="o">=</span> <span class="n">request</span><span class="o">.</span><span
class="na">getMethod</span><span class="o">();</span>
+ <span class="n">storage</span><span class="o">.</span><span
class="na">updateEntityData</span><span class="o">(</span><span
class="n">edmEntitySet</span><span class="o">,</span> <span
class="n">keyPredicates</span><span class="o">,</span> <span
class="n">requestEntity</span><span class="o">,</span> <span
class="n">httpMethod</span><span class="o">);</span>
+
+ <span class="c1">//3. configure the response object</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">NO_CONTENT</span><span class="o">.</span><span
class="na">getStatusCode</span><span class="o">());</span>
+<span class="o">}</span>
+</pre></div>
+
+
+<p>In case of update, we have to consider the following:<br />
+The update of an entity can be realized in 2 ways: either a
<strong>PATCH</strong> or a <strong>PUT</strong> request.<br />
+(See the online specification in section <a
href="http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part1-protocol.html">11.4.3
Update an Entity</a> for more details.
+For both HTTP methods, our <code>updateEntity(...)</code> will be invoked.<br
/>
+But we have to treat the data-modification differently.<br />
+Therefore, we have to first retrieve the used HTTP method and in the
backend-logic, we have to distinguish between <strong>PATCH</strong> and
<strong>PUT</strong>.<br />
+The difference becomes relevant only in case if the user doesnât send all
the properties in the request body. </p>
+<p>Example: if we modify the above example request body to look as follows:
</p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="nt">"Description"</span><span class="p">:</span><span
class="s2">"updated description"</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>Note that in this case, only one of three properties is sent in the request
body.</p>
+<ul>
+<li>If the HTTP method is <strong>PATCH</strong>:<br />
+ The value of the <em>Description</em> property is updated in the
backend.<br />
+ The values of the other properties remain untouched.</li>
+<li>If the HTTP method is <strong>PUT</strong>:<br />
+ The value of the <em>Description</em> property is updated in the
backend.<br />
+ The value of the other properties is set to null (exception: key
properties can never be null). </li>
+</ul>
+<p>So letâs have a look at our sample implementation in the
<code>Storage</code> class (see below for full sample code and also see the
attached zip file containing the whole sample project)</p>
+<div class="codehilite"><pre><span class="kd">private</span> <span
class="kt">void</span> <span class="nf">updateProduct</span><span
class="o">(</span><span class="n">EdmEntityType</span> <span
class="n">edmEntityType</span><span class="o">,</span> <span
class="n">List</span><span class="o"><</span><span
class="n">UriParameter</span><span class="o">></span> <span
class="n">keyParams</span><span class="o">,</span> <span
class="n">Entity</span> <span class="n">entity</span><span class="o">,</span>
<span class="n">HttpMethod</span> <span class="n">httpMethod</span><span
class="o">)</span>
+ <span class="kd">throws</span> <span
class="n">ODataApplicationException</span><span class="o">{</span>
+
+ <span class="n">Entity</span> <span class="n">productEntity</span> <span
class="o">=</span> <span class="n">getProduct</span><span
class="o">(</span><span class="n">edmEntityType</span><span class="o">,</span>
<span class="n">keyParams</span><span class="o">);</span>
+ <span class="k">if</span><span class="o">(</span><span
class="n">productEntity</span> <span class="o">==</span> <span
class="kc">null</span><span class="o">){</span>
+ <span class="k">throw</span> <span class="k">new</span> <span
class="nf">ODataApplicationException</span><span class="o">(</span><span
class="s">"Entity not found"</span><span class="o">,</span>
+ <span class="n">HttpStatusCode</span><span
class="o">.</span><span class="na">NOT_FOUND</span><span
class="o">.</span><span class="na">getStatusCode</span><span
class="o">(),</span> <span class="n">Locale</span><span class="o">.</span><span
class="na">ENGLISH</span><span class="o">);</span>
+ <span class="o">}</span>
+
+ <span class="c1">// loop over all properties and replace the values with the
values of the given payload</span>
+ <span class="c1">// Note: ignoring ComplexType, as we don't have it in
our odata model</span>
+ <span class="n">List</span><span class="o"><</span><span
class="n">Property</span><span class="o">></span> <span
class="n">existingProperties</span> <span class="o">=</span> <span
class="n">productEntity</span><span class="o">.</span><span
class="na">getProperties</span><span class="o">();</span>
+ <span class="k">for</span><span class="o">(</span><span
class="n">Property</span> <span class="n">existingProp</span> <span
class="o">:</span> <span class="n">existingProperties</span><span
class="o">){</span>
+ <span class="n">String</span> <span class="n">propName</span> <span
class="o">=</span> <span class="n">existingProp</span><span
class="o">.</span><span class="na">getName</span><span class="o">();</span>
+
+ <span class="c1">// ignore the key properties, they aren't
updateable</span>
+ <span class="k">if</span><span class="o">(</span><span
class="n">isKey</span><span class="o">(</span><span
class="n">edmEntityType</span><span class="o">,</span> <span
class="n">propName</span><span class="o">)){</span>
+ <span class="k">continue</span><span class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="n">Property</span> <span class="n">updateProperty</span>
<span class="o">=</span> <span class="n">entity</span><span
class="o">.</span><span class="na">getProperty</span><span
class="o">(</span><span class="n">propName</span><span class="o">);</span>
+ <span class="c1">// the request payload might not consider ALL properties,
so it can be null</span>
+ <span class="k">if</span><span class="o">(</span><span
class="n">updateProperty</span> <span class="o">==</span> <span
class="kc">null</span><span class="o">){</span>
+ <span class="c1">// if a property has NOT been added to the request
payload</span>
+ <span class="c1">// depending on the HttpMethod, our behavior is
different</span>
+ <span class="k">if</span><span class="o">(</span><span
class="n">httpMethod</span><span class="o">.</span><span
class="na">equals</span><span class="o">(</span><span
class="n">HttpMethod</span><span class="o">.</span><span
class="na">PATCH</span><span class="o">)){</span>
+ <span class="c1">// in case of PATCH, the existing property is not
touched</span>
+ <span class="k">continue</span><span class="o">;</span> <span
class="c1">// do nothing</span>
+ <span class="o">}</span><span class="k">else</span> <span
class="k">if</span><span class="o">(</span><span
class="n">httpMethod</span><span class="o">.</span><span
class="na">equals</span><span class="o">(</span><span
class="n">HttpMethod</span><span class="o">.</span><span
class="na">PUT</span><span class="o">)){</span>
+ <span class="c1">// in case of PUT, the existing property is set to
null</span>
+ <span class="n">existingProp</span><span class="o">.</span><span
class="na">setValue</span><span class="o">(</span><span
class="n">existingProp</span><span class="o">.</span><span
class="na">getValueType</span><span class="o">(),</span> <span
class="kc">null</span><span class="o">);</span>
+ <span class="k">continue</span><span class="o">;</span>
+ <span class="o">}</span>
+ <span class="o">}</span>
+
+ <span class="c1">// change the value of the properties</span>
+ <span class="n">existingProp</span><span class="o">.</span><span
class="na">setValue</span><span class="o">(</span><span
class="n">existingProp</span><span class="o">.</span><span
class="na">getValueType</span><span class="o">(),</span> <span
class="n">updateProperty</span><span class="o">.</span><span
class="na">getValue</span><span class="o">());</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</pre></div>
+
+
+<h2 id="33-implement-the-deleteentity-method">3.3. Implement the
deleteEntity(...) method</h2>
+<p>In case of <strong>DELETE</strong> operation, the URL is the same like for
the <strong>GET</strong> operation, but the request body is empty.</p>
+<p>Example URL:</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="p">(</span>3<span class="p">)</span>
+</pre></div>
+
+
+<p>The implementation is rather simple: </p>
+<ul>
+<li>As usual, determine the entity set. </li>
+<li>Delete the data in backend. </li>
+<li>
+<p>Configure the response object with the proper status code <strong>204 â
no content</strong>. </p>
+<div class="codehilite"><pre><span class="kd">public</span> <span
class="kt">void</span> <span class="nf">deleteEntity</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="kd">throws</span> <span
class="n">ODataApplicationException</span> <span class="o">{</span>
+
+ <span class="c1">// 1. Retrieve the entity set which belongs to the
requested entity</span>
+ <span class="n">List</span><span class="o"><</span><span
class="n">UriResource</span><span class="o">></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="c1">// Note: only in our example we can assume that the first
segment is the EntitySet</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">// 2. delete the data in backend</span>
+ <span class="n">List</span><span class="o"><</span><span
class="n">UriParameter</span><span class="o">></span> <span
class="n">keyPredicates</span> <span class="o">=</span> <span
class="n">uriResourceEntitySet</span><span class="o">.</span><span
class="na">getKeyPredicates</span><span class="o">();</span>
+ <span class="n">storage</span><span class="o">.</span><span
class="na">deleteEntityData</span><span class="o">(</span><span
class="n">edmEntitySet</span><span class="o">,</span> <span
class="n">keyPredicates</span><span class="o">);</span>
+
+ <span class="c1">//3. configure the response object</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">NO_CONTENT</span><span class="o">.</span><span
class="na">getStatusCode</span><span class="o">());</span>
+<span class="o">}</span>
+</pre></div>
+
+
+</li>
+</ul>
+<h2 id="34-run-the-service">3.4. Run the service</h2>
+<p>After building and deploying the project, we can invoke our OData
service.</p>
+<p>In order to test the write operations of our OData service, we need a tool
that is able to execute the following required HTTP requests:
<strong>POST</strong>, <strong>PUT</strong>, <strong>PATCH</strong>,
<strong>DELETE</strong><br />
+This is usually done with any REST client tool that can be installed into the
browser of your choice. </p>
+<p>Examples:<br />
+ - Firefox: âRESTClient, a debugger for RESTful web servicesâ<br />
+ - Chrome: âAdvanced REST clientâ </p>
+<p>The following sections provide examples for executing the requests:</p>
+<h3 id="341-example-for-create">3.4.1. Example for
<strong>CREATE</strong>:</h3>
+<ul>
+<li>URL: <a
href="http://localhost:8080/DemoService/DemoService.svc/Products">http://localhost:8080/DemoService/DemoService.svc/Products</a>
</li>
+<li>HTTP verb: <strong>POST</strong></li>
+<li>Header: <code>Content-Type: application/json;
odata.metadata=minimal</code> </li>
+<li>
+<p>Request body: </p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="nt">"ID"</span><span class="p">:</span><span
class="mi">6</span><span class="p">,</span>
+ <span class="nt">"Name"</span><span class="p">:</span><span
class="s2">"Gamer Mouse"</span><span class="p">,</span>
+ <span class="nt">"Description"</span><span class="p">:</span><span
class="s2">"optical mouse - gamer edition"</span>
+<span class="p">}</span>
+</pre></div>
+
+
+</li>
+</ul>
+<p>Note:
+The value for the ID property is arbitrary, as it will be generated by our
OData service implementation</p>
+<h3 id="342-example-for-update-put">3.4.2. Example for UPDATE (PUT):</h3>
+<ul>
+<li>URL: <a
href="http://localhost:8080/DemoService/DemoService.svc/Products(3)">http://localhost:8080/DemoService/DemoService.svc/Products(3)</a>
</li>
+<li>HTTP verb: <strong>PUT</strong></li>
+<li>Header: <code>Content-Type: application/json;
odata.metadata=minimal</code> </li>
+<li>
+<p>Request body: </p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="nt">"ID"</span><span class="p">:</span><span
class="mi">3</span><span class="p">,</span>
+ <span class="nt">"Name"</span><span class="p">:</span><span
class="s2">"Ergo Screen updated Name"</span><span class="p">,</span>
+ <span class="nt">"Description"</span><span class="p">:</span><span
class="s2">"updated description"</span>
+<span class="p">}</span>
+</pre></div>
+
+
+</li>
+</ul>
+<h3 id="343-example-for-update-patch">3.4.3. Example for UPDATE (PATCH):</h3>
+<ul>
+<li>URL: <a
href="http://localhost:8080/DemoService/DemoService.svc/Products(3)">http://localhost:8080/DemoService/DemoService.svc/Products(3)</a>
</li>
+<li>HTTP verb: <strong>PATCH</strong> </li>
+<li>Header: <code>Content-Type: application/json;
odata.metadata=minimal</code> </li>
+<li>
+<p>Request body: </p>
+<div class="codehilite"><pre><span class="p">{</span>
+ <span class="nt">"Description"</span><span class="p">:</span>
<span class="s2">"patched description"</span>
+<span class="p">}</span>
+</pre></div>
+
+
+</li>
+</ul>
+<h3 id="344-example-for-delete">3.4.4. Example for DELETE:</h3>
+<ul>
+<li>URL: <a
href="http://localhost:8080/DemoService/DemoService.svc/Products(3)">http://localhost:8080/DemoService/DemoService.svc/Products(3)</a>
</li>
+<li>HTTP verb: <strong>DELETE</strong> </li>
+<li>Header: Content-Type: application/json; odata.metadata=minimal </li>
+<li>Request body: <code><empty></code></li>
+</ul>
+<hr />
+<h1 id="4-summary">4. Summary</h1>
+<p>In this tutorial we have learned how to implement the creation, update and
deletion of an entity.<br />
+It has been based on a simple OData model, focusing on simple sample code and
sample data. </p>
+<p>In the next tutorial (Part 4: Navigation) we will learn how to implement
navigation, i.e. the linking of resources.</p>
+<hr />
+<h1 id="5-links">5. Links</h1>
+<p>Tutorial OData V4 service part 1: <a
href="/doc/odata4/tutorials/read/tutorial_read.html">Read Entity Collection</a>
| <a
href="/doc/odata4/tutorials/read/sample/DemoService_Tutorial_Read.zip">sample
project zip</a><br />
+Tutorial OData V4 service part 2: <a
href="/doc/odata4/tutorials/readep/tutorial_readep.html">Read Entity, Read
Property</a> | <a
href="/doc/odata4/tutorials/readep/sample/DemoService_Tutorial_Readep.zip">sample
project zip</a><br />
+Tutorial OData V4 service part 3: <a
href="/doc/odata4/tutorials/write/tutorial_write.html">Write (Create, Update,
Delete Entity) - (this page)</a> | <a
href="/doc/odata4/tutorials/write/sample/DemoService_Tutorial_Write.zip">sample
project zip</a><br />
+Tutorial OData V4 service, part 4: <a href="...">Navigation - (To Be
Announced)</a></p>
+<p>OData specification: <a href="http://odata.org/">http://odata.org/</a>
+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>