| <html><head> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <title xmlns:d="http://docbook.org/ns/docbook">Chapter 4. Porting Existing Code to Connect to a Web Service Instead of a Database</title><link rel="stylesheet" type="text/css" href="css/cayenne-doc.css"><meta xmlns:d="http://docbook.org/ns/docbook" name="keywords" content="Cayenne 4.0 documentation"><meta xmlns:d="http://docbook.org/ns/docbook" name="description" content="User documentation for Apache Cayenne version 4.0"><link rel="home" href="index.html" title="Getting Started with Cayenne ROP (Remote Object Persistence)"><link rel="up" href="getting-started-rop-part2.html" title="Part II. Remote Object Persistence Quick Start"><link rel="prev" href="ch03.html" title="Chapter 3. Setting up Hessian Web Service"><link rel="next" href="ch05.html" title="Chapter 5. Adding BASIC Authentication"><script xmlns:d="http://docbook.org/ns/docbook" type="text/javascript"> |
| var _gaq = _gaq || []; |
| _gaq.push(['_setAccount', 'UA-7036673-1']); |
| _gaq.push(['_trackPageview']); |
| (function() { |
| var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; |
| ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
| var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); |
| })(); |
| </script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div xmlns:d="http://docbook.org/ns/docbook" class="navheader"><table width="100%" summary="Navigation header"><tr><th class="versioninfo">v.4.0 (4.0.M5)</th><th align="center">Chapter 4. Porting Existing Code to Connect to a Web Service Instead of a Database</th><th></th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch03.html">Prev</a> </td><th width="60%" align="center"><a accesskey="u" href="getting-started-rop-part2.html">Part II. Remote Object Persistence Quick Start</a></th><td width="20%" align="right"> <a accesskey="n" href="ch05.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="d0e158"></a>Chapter 4. Porting Existing Code to Connect to a Web Service Instead of a Database</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="ch04.html#starting-command-line-cliet">Starting Command Line Client</a></span></dt></dl></div><div class="section"><div class="titlepage"><div><div><h2 class="title"><a name="starting-command-line-cliet"></a>Starting Command Line Client</h2></div></div></div><p>One of the benefits of ROP is that the client code is no different from the server |
| code - it uses the same ObjectContext interface for access, same query and commit API. |
| So the code below will be similar to the code presented in the first Cayenne |
| Getting Started Guide, although with a few ROP-specific parts required to bootstrap the |
| ObjectContext.</p><p>Let's start by creating an empty Main class with the standard main() method in the |
| client project:</p><pre class="programlisting"><span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">package</span> org.example.cayenne.persistent.client; |
| |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">public</span> <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span> Main { |
| |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">public</span> <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">static</span> <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">void</span> main(String[] args) { |
| |
| } |
| }</pre><p>Now the part that is actually different from regular Cayenne - establishing the server |
| connection and obtaining the ObjectContext:</p><pre class="programlisting">Map<String, String> properties = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> HashMap<>(); |
| properties.put(Constants.ROP_SERVICE_URL_PROPERTY, <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"http://localhost:8080/tutorial/cayenne-service"</span>); |
| properties.put(Constants.ROP_SERVICE_USERNAME_PROPERTY, <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"cayenne-user"</span>); |
| properties.put(Constants.ROP_SERVICE_PASSWORD_PROPERTY, <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"secret"</span>); |
| |
| ClientRuntime runtime = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> ClientRuntime(properties); |
| ObjectContext context = runtime.newContext(); </pre><p>Note that the "runtime" can be used to create as many peer ObjectContexts as needed |
| over the same connection, while ObjectContext is a kind of isolated "persistence |
| session", similar to the server-side context. A few more notes. Since we are using |
| HTTP(S) to communicate with ROP server, there's no need to explicitly close the |
| connection (or channel, or context).</p><p>So now let's do the same persistent operaions that we did in the first tutorial "Main" |
| class. Let's start by creating and saving some objects:</p><pre class="programlisting"><span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// creating new Artist</span> |
| Artist picasso = context.newObject(Artist.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>); |
| picasso.setName(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Pablo Picasso"</span>); |
| |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// Creating other objects</span> |
| Gallery metropolitan = context.newObject(Gallery.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>); |
| metropolitan.setName(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Metropolitan Museum of Art"</span>); |
| |
| Painting girl = context.newObject(Painting.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>); |
| girl.setName(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Girl Reading at a Table"</span>); |
| |
| Painting stein = context.newObject(Painting.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>); |
| stein.setName(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Gertrude Stein"</span>); |
| |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// connecting objects together via relationships</span> |
| picasso.addToPaintings(girl); |
| picasso.addToPaintings(stein); |
| |
| girl.setGallery(metropolitan); |
| stein.setGallery(metropolitan); |
| |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// saving all the changes above</span> |
| context.commitChanges();</pre><p>Now let's select them back:</p><pre class="programlisting"><span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// ObjectSelect examples</span> |
| List<Painting> paintings1 = ObjectSelect.query(Painting.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>).select(context); |
| |
| List<Painting> paintings2 = ObjectSelect.query(Painting.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>) |
| .where(Painting.NAME.likeIgnoreCase(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"gi%"</span>)).select(context); </pre><p>Now, delete:</p><pre class="programlisting"><span xmlns="http://www.w3.org/1999/xhtml" class="hl-comment">// Delete object example</span> |
| Artist picasso = ObjectSelect.query(Artist.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>).where(Artist.NAME.eq(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Pablo Picasso"</span>)).selectOne(context); |
| |
| <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">if</span> (picasso != null) { |
| context.deleteObject(picasso); |
| context.commitChanges(); |
| }</pre><p>This code is exactly the same as in the first tutorial. So now let's try running the |
| client and see what happens. In Eclipse open main class and select "Run > Run As > |
| Java Application" from the menu (assuming the ROP server started in the previous step is |
| still running). You will some output in both server and client process consoles. |
| Client:</p><pre class="programlisting">INFO: Connecting to [http://localhost:8080/tutorial/cayenne-service] - dedicated session. |
| INFO: === Connected, session: org.apache.cayenne.remote.RemoteSession@26544ec1[sessionId=17uub1h34r9x1] - took 111 ms. |
| INFO: --- Message 0: Bootstrap |
| INFO: === Message 0: Bootstrap done - took 58 ms. |
| INFO: --- Message 1: flush-cascade-sync |
| INFO: === Message 1: flush-cascade-sync done - took 1119 ms. |
| INFO: --- Message 2: Query |
| INFO: === Message 2: Query done - took 48 ms. |
| INFO: --- Message 3: Query |
| INFO: === Message 3: Query done - took 63 ms. |
| INFO: --- Message 4: Query |
| INFO: === Message 4: Query done - took 19 ms. |
| INFO: --- Message 5: Query |
| INFO: === Message 5: Query done - took 7 ms. |
| INFO: --- Message 6: Query |
| INFO: === Message 6: Query done - took 5 ms. |
| INFO: --- Message 7: Query |
| INFO: === Message 7: Query done - took 2 ms. |
| INFO: --- Message 8: Query |
| INFO: === Message 8: Query done - took 4 ms. |
| INFO: --- Message 9: flush-cascade-sync |
| INFO: === Message 9: flush-cascade-sync done - took 34 ms.</pre><p>As you see client prints no SQL statmenets, just a bunch of query and flush messages |
| sent to the server. The server side is more verbose, showing the actual client queries |
| executed against the database:</p><pre class="programlisting">... |
| INFO: SELECT NEXT_ID FROM AUTO_PK_SUPPORT WHERE TABLE_NAME = ? FOR UPDATE [bind: 1:'ARTIST'] |
| INFO: SELECT NEXT_ID FROM AUTO_PK_SUPPORT WHERE TABLE_NAME = ? FOR UPDATE [bind: 1:'GALLERY'] |
| INFO: SELECT NEXT_ID FROM AUTO_PK_SUPPORT WHERE TABLE_NAME = ? FOR UPDATE [bind: 1:'PAINTING'] |
| INFO: INSERT INTO ARTIST (DATE_OF_BIRTH, ID, NAME) VALUES (?, ?, ?) |
| INFO: [batch bind: 1->DATE_OF_BIRTH:NULL, 2->ID:200, 3->NAME:'Pablo Picasso'] |
| INFO: === updated 1 row. |
| INFO: INSERT INTO GALLERY (ID, NAME) VALUES (?, ?) |
| INFO: [batch bind: 1->ID:200, 2->NAME:'Metropolitan Museum of Art'] |
| INFO: === updated 1 row. |
| INFO: INSERT INTO PAINTING (ARTIST_ID, GALLERY_ID, ID, NAME) VALUES (?, ?, ?, ?) |
| INFO: [batch bind: 1->ARTIST_ID:200, 2->GALLERY_ID:200, 3->ID:200, 4->NAME:'Girl Reading at a Table'] |
| INFO: [batch bind: 1->ARTIST_ID:200, 2->GALLERY_ID:200, 3->ID:201, 4->NAME:'Gertrude Stein'] |
| INFO: === updated 2 rows. |
| INFO: +++ transaction committed. |
| INFO: --- transaction started. |
| INFO: SELECT t0.GALLERY_ID, t0.NAME, t0.ARTIST_ID, t0.ID FROM PAINTING t0 |
| INFO: === returned 2 rows. - took 14 ms. |
| INFO: +++ transaction committed. |
| INFO: --- transaction started. |
| INFO: SELECT t0.GALLERY_ID, t0.NAME, t0.ARTIST_ID, t0.ID FROM PAINTING t0 |
| WHERE UPPER(t0.NAME) LIKE UPPER(?) [bind: 1->NAME:'gi%'] |
| INFO: === returned 1 row. - took 10 ms. |
| INFO: +++ transaction committed. |
| INFO: --- transaction started. |
| INFO: SELECT t0.DATE_OF_BIRTH, t0.NAME, t0.ID FROM ARTIST t0 WHERE t0.NAME = ? [bind: 1->NAME:'Pablo Picasso'] |
| INFO: === returned 1 row. - took 8 ms. |
| INFO: +++ transaction committed. |
| INFO: --- transaction started. |
| INFO: DELETE FROM PAINTING WHERE ID = ? |
| INFO: [batch bind: 1->ID:200] |
| INFO: [batch bind: 1->ID:201] |
| INFO: === updated 2 rows. |
| INFO: DELETE FROM ARTIST WHERE ID = ? |
| INFO: [batch bind: 1->ID:200] |
| INFO: === updated 1 row. |
| INFO: +++ transaction committed.</pre><p>You are done with the basic ROP client!</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch03.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="getting-started-rop-part2.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="ch05.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 3. Setting up Hessian Web Service </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 5. Adding BASIC Authentication</td></tr></table></div></body></html> |