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/05/19 11:20:02 UTC
svn commit: r951850 - in /websites/staging/olingo/trunk/content: ./
doc/odata4/tutorials/write/ doc/odata4/tutorials/write/tutorial_write.html
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>