blob: 83545644de764c5fa96e81c98ded2070dd5002e3 [file] [log] [blame]
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title xmlns:d="http://docbook.org/ns/docbook">Chapter&nbsp;4.&nbsp;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 3.1 documentation"><meta xmlns:d="http://docbook.org/ns/docbook" name="description" content="User documentation for Apache Cayenne version 3.1"><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&nbsp;II.&nbsp;Remote Object Persistence Quick Start"><link rel="prev" href="ch03.html" title="Chapter&nbsp;3.&nbsp;Setting up Hessian Web Service"><link rel="next" href="ch05.html" title="Chapter&nbsp;5.&nbsp;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.3.1 (3.1)</th><th align="center">Chapter&nbsp;4.&nbsp;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>&nbsp;</td><th width="60%" align="center"><a accesskey="u" href="getting-started-rop-part2.html">Part&nbsp;II.&nbsp;Remote Object Persistence Quick Start</a></th><td width="20%" align="right">&nbsp;<a accesskey="n" href="ch05.html">Next</a></td></tr></table><hr></div><div class="chapter" title="Chapter&nbsp;4.&nbsp;Porting Existing Code to Connect to a Web Service Instead of a Database"><div class="titlepage"><div><div><h2 class="title"><a name="d0e157"></a>Chapter&nbsp;4.&nbsp;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><dt><span class="section"><a href="ch04.html#starting-command-line-cliet">Starting Command Line Client</a></span></dt></dl></div><div class="section" title="Starting Command Line Client"><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">ClientConnection connection = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> HessianConnection(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"http://localhost:8080/tutorial/cayenne-service"</span>);
DataChannel channel = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> ClientChannel(connection, false, <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> DefaultEventManager(), false);
ObjectContext context = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> CayenneContext(channel);</pre><p>Note that the "channel" 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">// SelectQuery examples</span>
SelectQuery select1 = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> SelectQuery(Painting.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>);
List&lt;Painting&gt; paintings1 = context.performQuery(select1);
Expression qualifier2 = ExpressionFactory.likeIgnoreCaseExp(
Painting.NAME_PROPERTY, <span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"gi%"</span>);
SelectQuery select2 = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> SelectQuery(Painting.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>, qualifier2);
List&lt;Painting&gt; paintings2 = context.performQuery(select2);</pre><p>Now, delete:</p><pre class="programlisting">Expression qualifier = ExpressionFactory.matchExp(Artist.NAME_PROPERTY,
<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"Pablo Picasso"</span>);
SelectQuery selectToDelete = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> SelectQuery(Artist.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>, qualifier);
Artist picasso = (Artist) DataObjectUtils.objectForQuery(context,
selectToDelete);
<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 &gt; Run As &gt;
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-&gt;DATE_OF_BIRTH:NULL, 2-&gt;ID:200, 3-&gt;NAME:'Pablo Picasso']
INFO: === updated 1 row.
INFO: INSERT INTO GALLERY (ID, NAME) VALUES (?, ?)
INFO: [batch bind: 1-&gt;ID:200, 2-&gt;NAME:'Metropolitan Museum of Art']
INFO: === updated 1 row.
INFO: INSERT INTO PAINTING (ARTIST_ID, GALLERY_ID, ID, NAME) VALUES (?, ?, ?, ?)
INFO: [batch bind: 1-&gt;ARTIST_ID:200, 2-&gt;GALLERY_ID:200, 3-&gt;ID:200, 4-&gt;NAME:'Girl Reading at a Table']
INFO: [batch bind: 1-&gt;ARTIST_ID:200, 2-&gt;GALLERY_ID:200, 3-&gt;ID:201, 4-&gt;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-&gt;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-&gt;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-&gt;ID:200]
INFO: [batch bind: 1-&gt;ID:201]
INFO: === updated 2 rows.
INFO: DELETE FROM ARTIST WHERE ID = ?
INFO: [batch bind: 1-&gt;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>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="getting-started-rop-part2.html">Up</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="ch05.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter&nbsp;3.&nbsp;Setting up Hessian Web Service&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;Chapter&nbsp;5.&nbsp;Adding BASIC Authentication</td></tr></table></div></body></html>