<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Software Blog</title>
	<atom:link href="http://tetyana.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://tetyana.wordpress.com</link>
	<description>Just another WordPress.com weblog</description>
	<lastBuildDate>Fri, 08 Feb 2008 10:18:10 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='tetyana.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/d00528c06543aef51910120473fedb6f?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Software Blog</title>
		<link>http://tetyana.wordpress.com</link>
	</image>
			<item>
		<title>XP Forum in JHB</title>
		<link>http://tetyana.wordpress.com/2008/02/08/xp-forum-in-jhb/</link>
		<comments>http://tetyana.wordpress.com/2008/02/08/xp-forum-in-jhb/#comments</comments>
		<pubDate>Fri, 08 Feb 2008 10:18:10 +0000</pubDate>
		<dc:creator>tetyana</dc:creator>
				<category><![CDATA[Persistence]]></category>
		<category><![CDATA[contract]]></category>
		<category><![CDATA[Saas]]></category>
		<category><![CDATA[XP]]></category>

		<guid isPermaLink="false">http://tetyana.wordpress.com/?p=11</guid>
		<description><![CDATA[Yesterday we had an interesting event in Wits university  -  a presentation about implementing XP in customer contracts. Looks like making a contract can be a real challenge, but that&#8217;s the only way to go. The suggested model for XP: fixed cost contract. The idea is to disclose your costs and expected profit to the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=11&subd=tetyana&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Yesterday we had an interesting event in Wits university  -  a presentation about implementing XP in customer contracts. Looks like making a contract can be a real challenge, but that&#8217;s the only way to go. The suggested model for XP: fixed cost contract. The idea is to disclose your costs and expected profit to the customer, set a target time and define the scope on a very-high level. The high-level definition of the scope allows both parties to negotiate on the specific module (requires lots of trust).  Disclosing your costs&amp;profits is supposed to improve the trust relationship. The negotiation on modules is certainly something not clear enough, especially if the client in the beginning has no idea of what they want (which is often the case).</p>
<p>Otherwise, I feel quite scared, &#8211; probably writing software on demand is very risky. I&#8217;m rather looking at SaaS.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/tetyana.wordpress.com/11/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/tetyana.wordpress.com/11/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tetyana.wordpress.com/11/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tetyana.wordpress.com/11/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tetyana.wordpress.com/11/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tetyana.wordpress.com/11/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tetyana.wordpress.com/11/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tetyana.wordpress.com/11/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tetyana.wordpress.com/11/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tetyana.wordpress.com/11/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tetyana.wordpress.com/11/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tetyana.wordpress.com/11/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=11&subd=tetyana&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://tetyana.wordpress.com/2008/02/08/xp-forum-in-jhb/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f46caecbce7147b5aadfc92fc45cc2f5?s=96&#38;d=identicon" medium="image">
			<media:title type="html">tetyana</media:title>
		</media:content>
	</item>
		<item>
		<title>Make Your Program Write Code For You</title>
		<link>http://tetyana.wordpress.com/2007/12/07/make-your-program-write-code-for-you/</link>
		<comments>http://tetyana.wordpress.com/2007/12/07/make-your-program-write-code-for-you/#comments</comments>
		<pubDate>Fri, 07 Dec 2007 16:55:47 +0000</pubDate>
		<dc:creator>tetyana</dc:creator>
				<category><![CDATA[Code Generation]]></category>
		<category><![CDATA[PLSQL]]></category>
		<category><![CDATA[StringTemplate]]></category>

		<guid isPermaLink="false">http://tetyana.wordpress.com/2007/12/07/make-your-program-write-code-for-you/</guid>
		<description><![CDATA[I’m back to writing PLSQL and it’s pain as always. Recently I was dealing with the issue of synchronizing table data between 2 databases and needed to provide a comparison report about the values that do not match. Well, that’s easy: select rows locally and over the dblink and compare the data. But… what if [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=10&subd=tetyana&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p class="MsoNormal"><span style="font-size:8pt;">I’m back to writing PLSQL and it’s pain as always. Recently I was dealing with the issue of synchronizing table data between 2 databases and needed to provide a comparison report about the values that do not match. Well, that’s easy: select rows locally and over the dblink and compare the data. But… what if there are 40 different tables to compare and hundreds of selection criteria to get the data? And no, I do not have time to type it all.</span></p>
<p class="MsoNormal"><span style="font-size:8pt;">So I needed some sort of automation. Of course PLSQL provides something:</span></p>
<p class="MsoNormal" style="margin-left:36pt;text-indent:-18pt;"><!--[if !supportLists]--><span style="font-size:8pt;"><span>-<span style="font-family:'Times New Roman';font-style:normal;font-variant:normal;font-weight:normal;font-size:7pt;line-height:normal;">          </span></span></span><!--[endif]--><span style="font-size:8pt;">I can use one procedure to populate collections using the selection criteria;</span></p>
<p class="MsoNormal" style="margin-left:36pt;text-indent:-18pt;"><!--[if !supportLists]--><span style="font-size:8pt;"><span>-<span style="font-family:'Times New Roman';font-style:normal;font-variant:normal;font-weight:normal;font-size:7pt;line-height:normal;">          </span></span></span><!--[endif]--><span style="font-size:8pt;">another procedure can check the same primary keys exist in the local and remote collection;</span></p>
<p class="MsoNormal" style="margin-left:36pt;text-indent:-18pt;"><!--[if !supportLists]--><span style="font-size:8pt;"><span>-<span style="font-family:'Times New Roman';font-style:normal;font-variant:normal;font-weight:normal;font-size:7pt;line-height:normal;">          </span></span></span><!--[endif]--><span style="font-size:8pt;">and the last one can browse through a pair of collection rows to compare that all fields have the same values.</span></p>
<p class="MsoNormal"><span style="font-size:8pt;">That sounds reasonable and short. But each collection should represent a row in a table (something like MyTable%rowtype), that means that collections for different tables will be completely different. So how to make it generic (especially in the case when all fields are to be compared)? </span></p>
<p class="MsoNormal"><span style="font-size:8pt;">I did not found any elegant answer in PLSQL and typing code for all table variations seemed to be impossible. I had to look for a better solution and I decided to use code patterns and replace pieces that do not match. Thanks to <a href="http://www.stringtemplate.org/">StringTemplate</a> the work turned to be really easy. StringTemplate allows separation of your code from the template code. The benefit here is that the template looks semantically the same as the result, so it is very easy to create, correct and maintain. In the same time the code stays clean and very simple. Though StringTemplate has a rich API, I basically mastered only a small piece of it in 5 minutes and that was far enough to do the entire job.</span></p>
<p class="MsoNormal"><span style="font-size:8pt;">For those who are still interested, here is an example. </span></p>
<h2>Example</h2>
<p class="MsoNormal"><span style="font-size:8pt;">Imagine we have a list of tables (Table1, Table2, Table3 for instance) in 2 databases connected over a db link; the tables can have any amount of fields with different names. Our goal is to compare all the values in matching tables between 2 databases, i.e. first we will check that all IDs<span>  </span>from local database table are present in the remote table and then we will compare that the rows with the same ID have all other fields with the same values.</span></p>
<p class="MsoNormal"><span style="font-size:8pt;">To make it shorter let’s imagine that the code populating data into Table1%rowtype (Table2%rowtype, Table3%rowtype etc) collections is already generated. So we will need the following templates (I’ve started by writing this code manually for 1 table to be sure about the template syntax):</span></p>
<p class="MsoNormal"><span style="font-size:8pt;"> </span></p>
<h2>Templates</h2>
<p class="MsoNormal"><span style="font-size:8pt;">In all the templates below $$ is used to distinguish a replaceable attribute.</span></p>
<p class="MsoNormal"><span style="font-size:8pt;"> </span></p>
<h3>compare.st – Top-level checking function:</h3>
<p class="MsoNormal"><span style="font-size:8pt;">&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';">procedure $compare_procedure_name$($local_table$ $table_type$,<br />
$remote_table$ $table_type$) is </span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';"><span>       </span></span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';"><span>    </span>rec_id integer;<br />
<span></span>column varchar2(30);<br />
<span></span>begin<br />
<span></span>    for i in 1 .. $local_table$.count<br />
<span></span>    loop<br />
<span></span>        rec_id := $find_procedure_name$($remote_table$, $local_table$(i).id);<span><br />
</span>        if rec_id &lt; 0 then<br />
<span></span>            log_error(&#8216;Missing $entity_name$: &#8216;|| <span> </span>$local_table$(i).id);<br />
<span></span>            error_count := error_count + 1;<br />
<span></span>        else<br />
<span></span>            if not $compare_function_name$($local_table$(i), $remote_table$(i), column) then<span><br />
</span>                log_error(&#8216;Different values observed in $entity_name$.&#8217; || column || ‘:’ ||$local_table$(i).id);<br />
<span></span><span></span>                error_count := error_count + 1;<br />
<span></span>            end if;<br />
<span></span>        end if;<br />
<span></span>    end loop;<span></span><br />
end;</span></p>
<p class="MsoNormal"><span style="font-size:8pt;"> </span></p>
<h3>find.st Function to locate a matching record in a collection</h3>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';">function $find_function_name$($generic_table$ $table_type$, $entity_id$ varchar2)<br />
<span></span><span></span>return integer<br />
<span></span>is<br />
<span></span>begin<br />
<span></span>    for i in 1 .. $generic_table$.count<br />
<span></span>    loop<br />
<span></span>        if $generic_table$(i).id = $entity_id$ then<br />
<span></span>            return i;<br />
<span></span>        end if;<span><br />
</span>    end loop;<span><br />
</span>    return -1;<br />
<span></span>end $find_function_name$;</span></p>
<p class="MsoNormal"><span style="font-size:8pt;"> </span></p>
<h3>compare_row.st Function to compare a selected row</h3>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';">function $compare_function_name$(local_entities edh_core.$entity_name$%rowtype,<br />
<span></span>                                 remote_entities edh_core.$entity_name$%rowtype,<br />
<span></span>                                 column out varchar2) return boolean<br />
<span></span>is<br />
<span></span>begin<br />
<span></span>    $compare_declarations$<br />
<span></span>    return true;<br />
<span></span>end $compare_function_name$;</span></p>
<p class="MsoNormal"><span style="font-size:8pt;"> </span></p>
<h3>compare_field.st A piece of code to compare a single field value:</h3>
<p class="MsoNormal"><span style="font-size:8pt;"><span>          </span><span> </span></span><span style="font-size:8pt;font-family:'Courier New';">if local_entities.$field_name$ &lt;&gt; remote_entities.$field_name$ then<br />
<span></span>    column := &#8216;$field_name$&#8217;;<br />
<span></span>    return false;<br />
<span></span>end if;</span></p>
<p class="MsoNormal"><span style="font-size:8pt;"> </span></p>
<p class="MsoNormal"><span style="font-size:8pt;"> </span></p>
<h2>Filling the templates</h2>
<p class="MsoNormal"><span style="font-size:8pt;">Now that the templates are ready, we will only need to apply them for all tables and fields and write to a file (I used a package template too, which you can easily create yourself).</span></p>
<p class="MsoNormal"><span style="font-size:8pt;"> </span></p>
<p class="MsoNormal"><span style="font-size:8pt;">General way to call a template:</span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';">// Templates are stored in templatesFolder<br />
StringTemplateGroup group = <strong>new</strong> StringTemplateGroup(&#8220;GroupName&#8221;,<br />
<span></span>&#8220;templatesFolder&#8221;, DefaultTemplateLexer.<strong>class</strong>);</span></p>
<p class="MsoNormal"><span style="font-size:8pt;">You can make group variable a class field as it will be used in all the template-handling procedures.</span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';">// compare is the name of template file without “.st” extension<br />
StringTemplate procedure = group.getInstanceOf(&#8220;compare&#8221;);</span></p>
<p class="MsoNormal"><span style="font-size:8pt;"> </span></p>
<p class="MsoNormal"><span style="font-size:8pt;">Now we need to set all the attributes used in the template</span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';"> </span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';">// Compare procedure name can be generated based on table name and selection criteria: compare_table1_description, compare_table2_time etc<br />
procedure.setAttribute(&#8220;compare_procedure_name &#8220;, “compare_” + tableName + “_” + criteria);<br />
procedure.setAttribute(&#8220;local_table&#8221;, tableName + “_local”);<br />
procedure.setAttribute(&#8220;table_type&#8221;, “t_” + tableName);<br />
procedure.setAttribute(&#8220;remote_table&#8221;, tableName + “_remote”);<br />
procedure.setAttribute(&#8220;find_procedure_name&#8221;,“compare_” + tableName + “_” + criteria);<br />
procedure.setAttribute(&#8220;entity&#8221;, tableName + “_remote”);<br />
// You can type the result or return it as the function result<br />
System.out.println(procedure.toString());<br />
return procedure.toString();</span></p>
<p class="MsoNormal"><span style="font-size:8pt;"> </span></p>
<p class="MsoNormal"><span style="font-size:8pt;">In an analogous way you can get the result from find.st template.</span></p>
<p class="MsoNormal"><span style="font-size:8pt;"> </span></p>
<p class="MsoNormal"><span style="font-size:8pt;">A bit more work is to use compare_row and compare_field templates, as compare_field template must be used inside compare_row as many times as there are fields in a row:</span></p>
<p class="MsoNormal"><span style="font-size:8pt;"> </span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';"> </span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';"> </span></p>
<p class="MsoNormal"><strong><span style="font-size:8pt;font-family:'Courier New';">public</span></strong><span style="font-size:8pt;font-family:'Courier New';"> String generateCompare() {<br />
<span></span>    StringTemplate procedure = group.getInstanceOf(&#8220;compare_row&#8221;);<br />
<span></span>    procedure.setAttribute(&#8220;compare_function_name&#8221;, getCompareProcedureName());<br />
<span></span>    procedure.setAttribute(&#8220;entity_name&#8221;, tableName);<br />
<span></span>    procedure.setAttribute(&#8220;compare_declarations&#8221;, <em>getCompareTemplate</em>(tableName));<br />
<span></span>    System.out.println(procedure.toString());<br />
<span></span><strong>    return</strong> procedure.toString();<br />
<span></span>}</span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';"><span>       </span></span></p>
<p class="MsoNormal"><strong><span style="font-size:8pt;font-family:'Courier New';">public</span></strong><span style="font-size:8pt;font-family:'Courier New';"> String getCompareTemplate(String tableName) {<br />
<span></span><strong>    if</strong> (entityName == &#8220;Table1&#8243;) {<br />
<span></span><strong>        return</strong> <em>getCompareTemplate</em>(<strong>new</strong> String[]{&#8220;Table1Field1&#8243;, &#8221; Table1Field2&#8243;, &#8221; Table1Field3&#8243;});<br />
<span></span>    } <strong>else</strong> <strong>if</strong> (entityName == &#8220;Table2&#8243;){<br />
<span></span><strong>        return</strong> <em>getCompareTemplate</em>(<strong>new</strong> String[]{&#8220;Table2Field1&#8243;, &#8221; Table2Field2&#8243;});<br />
<span></span>    } <strong>else</strong> <strong>if ( </strong> </span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';">         ///………</span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';"><span>               </span>    }<br />
return &#8220;&#8221;;<br />
}</span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';"> </span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';"> </span></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:'Courier New';"><span>              </span></span></p>
<p class="MsoNormal"><strong><span style="font-size:8pt;font-family:'Courier New';">private</span></strong><span style="font-size:8pt;font-family:'Courier New';"> String getCompareTemplate(String[] fields) {<br />
<span></span>    String compares = &#8220;&#8221;;<br />
<span></span><strong>    for</strong> (<strong>int</strong> i = 0; i &lt; fields.length; i++){<br />
<span></span>        StringTemplate template = <em>group</em>.getInstanceOf(&#8220;compare_field&#8221;);<br />
<span></span>        template.setAttribute(&#8220;field_name&#8221;, fields[i]);<br />
<span></span>        compares += template.toString() + &#8220;\r\n&#8221;;<br />
<span></span><span></span>    }<br />
<span></span><strong>    return</strong> compares;<br />
<span></span>}<span>      </span></span></p>
<p class="MsoNormal"><span style="font-size:8pt;color:black;"> </span></p>
<p class="MsoNormal"><span style="font-size:8pt;color:black;">Now instead of typing all these procedures for all the tables, you can just specify which table you are interested in, and then pass the columns array to getCompareTemplate.</span></p>
<p class="MsoNormal"><span style="font-size:8pt;color:black;">In this example I do not show how to put all the procedures and functions together in a PLSQL package file and how to fill table rows collections. However, you will be able to add those simple templates yourself and write the result into *.pck file.</span></p>
<p class="MsoNormal"><span style="font-size:8pt;color:black;">In general StringTemplate can save you lots of copy-pasting work and help to tame PLSQL, html, xml and other code.</span><span style="font-size:8pt;"></span></p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/tetyana.wordpress.com/10/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/tetyana.wordpress.com/10/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tetyana.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tetyana.wordpress.com/10/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tetyana.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tetyana.wordpress.com/10/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tetyana.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tetyana.wordpress.com/10/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tetyana.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tetyana.wordpress.com/10/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tetyana.wordpress.com/10/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tetyana.wordpress.com/10/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=10&subd=tetyana&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://tetyana.wordpress.com/2007/12/07/make-your-program-write-code-for-you/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f46caecbce7147b5aadfc92fc45cc2f5?s=96&#38;d=identicon" medium="image">
			<media:title type="html">tetyana</media:title>
		</media:content>
	</item>
		<item>
		<title>Using a Database Over a Webservice</title>
		<link>http://tetyana.wordpress.com/2007/05/28/using-a-database-over-a-webservice/</link>
		<comments>http://tetyana.wordpress.com/2007/05/28/using-a-database-over-a-webservice/#comments</comments>
		<pubDate>Mon, 28 May 2007 18:24:03 +0000</pubDate>
		<dc:creator>tetyana</dc:creator>
				<category><![CDATA[.NET Remoting]]></category>
		<category><![CDATA[Marshal By Value]]></category>
		<category><![CDATA[Persistence]]></category>
		<category><![CDATA[db4o]]></category>

		<guid isPermaLink="false">http://tetyana.wordpress.com/2007/05/28/using-a-database-over-a-webservice/</guid>
		<description><![CDATA[ Download source code &#8211; 780 kB
Introduction
RemotingService project was developed as a simple proof of concept (the idea taken
from Database as a Webservice). It is just one more way to realize a remote persistence.
In fact, putting any database on a web-server and providing a remote user interface to it, will realize the same idea from [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=9&subd=tetyana&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><a href="http://www.codeproject.com/useritems/RemotingDatabaseService/RemotingDatabaseService.zip"> Download source code &#8211; 780 kB</a></p>
<h2>Introduction</h2>
<p>RemotingService project was developed as a simple proof of concept (the idea taken<br />
from <a href="http://krispy.wordpress.com/2007/05/23/hello-world/">Database as a Webservice</a>). It is just one more way to realize a remote persistence.</p>
<p>In fact, putting any database on a web-server and providing a remote user interface to it, will realize the same idea from a user point of view. The interesting point of this solution is in the fact that no extra interface is developed, actually database interface is just transferred over the network.</p>
<p>This realization is possible due to the simple object-oriented interface provided by <a href="http://www.db4o.com">db4o</a> database.</p>
<p>A possible implementation can be in providing personal web-based databases for remote<br />
customers. Assuming that each user will use only one and his own database, this solution seems to be viable, providing the data is personally encrypted and unique database names are used.</p>
<h2>Background</h2>
<p>This article was inspired by <a href="http://krispy.wordpress.com/2007/05/23/hello-world/">Krispy Blog</a>.</p>
<h2>     Solution Organization</h2>
<p>RemotingXml consists of 4 projects:</p>
<ul>
<li>Db4objects.Db4o: db4o open-source database. Please, refer to db4o.license.html for licensing information. The code was slightly modified, which will be discussed later.</li>
<li>            Server: contains the code for a remote server. Server project is responsible for creating and starting remoting services.</li>
<li>RemotingExample: contains the code for creating persistent objects, sending them for serialization to the server and requesting the server for objects from the database.</li>
<li>RemotingClasses project is a library containing the definitions for classes to be<br />
persisted.</li>
</ul>
<h2>         Remoting Classes</h2>
<p>RemotingClasses project contains only one test class, which will be used on the client to be stored on the server. The class must have <code>Serializable</code> attribute to be transferrable over the network:</p>
<pre>[Serializable]public class TestValue

{

…

}</pre>
<h2>db4o Database Amendments</h2>
<p>In order to send the persistent classes from the client to the server we will need a Marshal-By-Reference object. This can be any class providing access to an ObjectContainer (can be modified ObjectContainer itself). The requirements to the transport object:</p>
<ul>
<li>the transport object should open a database file on request (filename should be provided somehow);</li>
<li>the transport object must have zero-parameters constructor.</li>
</ul>
<p>With the first implementation I tried to modify the ObjectContainer interface and the implementing classes. However it resulted in quite a lot of modifications as the hierarchy is<br />
deep. Moreover, I could not find a logical place to pass a filename to the object container (default implementation requires it in the constructor, and our rules need a parameterless constructor).</p>
<p>In the implementation, provided in this example, I use a version of Db4oFactory class, which can work over the network and can provide ObjectContainers for client requests:</p>
<pre>
using System;
using System.IO;
using Db4objects.Db4o;
using Db4objects.Db4o.Config;
using Db4objects.Db4o.Ext;
using Db4objects.Db4o.Foundation;
using Db4objects.Db4o.Foundation.Network;
using Db4objects.Db4o.Internal;
using Db4objects.Db4o.Internal.CS;
using Db4objects.Db4o.Reflect;

namespace Db4objects.Db4o
{
    ///
    /// This class simply duplicates Db4oFactory with
    /// instance methods, thus allowing Marshalling to
    /// access them
    ///
	public class Db4oRemoteFactory: MarshalByRefObject
	{
		internal static readonly Config4Impl i_config = new Config4Impl();

		public  IConfiguration NewConfiguration()
		{
            		return Db4oFactory.NewConfiguration();
		}

		public IConfiguration CloneConfiguration()
		{
			return (Config4Impl)((IDeepClone)Db4oFactory.Configure()).DeepClone(null);
		}

		public  IObjectContainer OpenFile(string databaseFileName)
		{
			return OpenFile(CloneConfiguration(), databaseFileName);
		}

		public IObjectContainer OpenFile(IConfiguration config, string databaseFileName
			)
		{
			return ObjectContainerFactory.OpenObjectContainer(config, databaseFileName);
		}

	}
}</pre>
<p>This implementation is convenient for clients working separately. However, it is not suitable for concurrent collaborative work on the same database file.</p>
<p>Another important change to the db4o sources: some of the internal classes representing persistent objects were marked <code>[Serializable]</code> to be suitable for over-network transmission.</p>
<h2>         Server</h2>
<p>The Server project is presented by a single <code>Program </code>class, which role is to start <code>Db4oRemoteFactory</code> service:</p>
<pre>
    class Program
    {
        static void Main(string[] args)
        {
            // Setting up tcp channel
            BinaryClientFormatterSinkProvider clientProvider = null;

            BinaryServerFormatterSinkProvider serverProvider =
                new BinaryServerFormatterSinkProvider();

            serverProvider.TypeFilterLevel =
                System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            IDictionary props = new Hashtable();

            /*
             * Client and server must use the SAME port
             * */
            props["port"] = 65101;
            props["typeFilterLevel"] = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            TcpChannel chan =
                new TcpChannel(props, clientProvider, serverProvider);

            ChannelServices.RegisterChannel(chan);

            Type TestFactory = Type.GetType("Db4objects.Db4o.Db4oRemoteFactory, Db4objects.Db4o");
            RemotingConfiguration.RegisterWellKnownServiceType(
                    TestFactory,
                    "TestFactoryEndPoint",
                    WellKnownObjectMode.Singleton
                );
            Console.WriteLine("TestFactory is ready.");

            // Keep the server running until the user presses
            // the Enter key.
            Console.WriteLine("Services are running. Press Enter to end...");
            Console.ReadLine();
        }
        // end Main

    }</pre>
<h2>Client</h2>
<p>Client project contains <code>Program</code> class.<span>  </span></p>
<p>In the constructor a connection to the <code>Db4oRemoteFactory</code> service is established:</p>
<pre>
      public Program()
        {
            string url;

            // Setup a client channel to our services.
            url = @"tcp://LocalHost:65101/";
            BinaryClientFormatterSinkProvider clientProvider =
                new BinaryClientFormatterSinkProvider();

            BinaryServerFormatterSinkProvider serverProvider =
                new BinaryServerFormatterSinkProvider();

            serverProvider.TypeFilterLevel =
                System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            IDictionary props = new Hashtable();
            props["port"] = 0;
            props["name"] = System.Guid.NewGuid().ToString();
            props["typeFilterLevel"] = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

            TcpChannel chan =
                new TcpChannel(props, clientProvider, serverProvider);
            ChannelServices.RegisterChannel(chan);

            // Set an access to the remote proxy
            factory = (Db4oRemoteFactory)RemotingServices.Connect(
                typeof(Db4oRemoteFactory), url + "TestFactoryEndPoint"
                );
        }
        // end Program</pre>
<p>The RunTest method creates a test object, sends it to the server using factory and retrieves it from the database on the server:</p>
<pre>
        private void RunTest()
        {
            // Remote persistent class
            TestValue testValue;
            testValue = new TestValue();
            // Modify local TestValue object
            testValue.ChangeData("Test value");
            // Pass testValue to the server through testServer
            // and store the testValue object
            IObjectContainer testServer = factory.OpenFile("test.db4o");
            testServer.Set(testValue);
            // Test what is stored to the database
            IList result = testServer.Get(typeof(TestValue));
            //TestValue test;
            foreach (TestValue test in result) {
                System.Console.WriteLine(test);
            }
        }
        // end RunTest</pre>
<h2>Points of Interest</h2>
<ul>
<li>The most interesting TO-DO on this project is, of course, its performance. How much information is transferred over the network for a single request? How is it comparable to the client-server version of db4o?</li>
<li>Are there any advantages over client-server version of db4o?</li>
<li>This implementation can only work over tcp-channel. Is it possible to realize the same functionality over html-channel?</li>
<li>How to realize concurrency control?</li>
</ul>
<h2>History</h2>
<p>2007-05-28 First version.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/tetyana.wordpress.com/9/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/tetyana.wordpress.com/9/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tetyana.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tetyana.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tetyana.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tetyana.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tetyana.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tetyana.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tetyana.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tetyana.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tetyana.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tetyana.wordpress.com/9/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=9&subd=tetyana&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://tetyana.wordpress.com/2007/05/28/using-a-database-over-a-webservice/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f46caecbce7147b5aadfc92fc45cc2f5?s=96&#38;d=identicon" medium="image">
			<media:title type="html">tetyana</media:title>
		</media:content>
	</item>
		<item>
		<title>Marshal By Value for Persistence</title>
		<link>http://tetyana.wordpress.com/2007/05/25/marshal-by-value-for-persistence/</link>
		<comments>http://tetyana.wordpress.com/2007/05/25/marshal-by-value-for-persistence/#comments</comments>
		<pubDate>Fri, 25 May 2007 09:21:58 +0000</pubDate>
		<dc:creator>tetyana</dc:creator>
				<category><![CDATA[.NET Remoting]]></category>
		<category><![CDATA[Marshal By Value]]></category>
		<category><![CDATA[Persistence]]></category>
		<category><![CDATA[Xml]]></category>

		<guid isPermaLink="false">http://tetyana.wordpress.com/2007/05/25/marshal-by-value-for-persistence/</guid>
		<description><![CDATA[I was recently writing about how to use Marshal By Value with db4o and was very surprised how little information could I found on this actually simple subject.
So, to contribute to the global network &#8211; here is another Marshal By Value example, this time with xml.
Download RemotingXml.zip &#8211; 11.3 KB
Introduction
RemotingXml project was
developed with 2 purposes [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=7&subd=tetyana&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I was recently writing about how to use Marshal By Value with db4o and was very surprised how little information could I found on this actually simple subject.</p>
<p>So, to contribute to the global network &#8211; here is another Marshal By Value example, this time with xml.</p>
<p><a href="http://www.codeproject.com/csharp/RemotingXml/RemotingXml.zip">Download RemotingXml.zip &#8211; 11.3 KB</a></p>
<h2>Introduction</h2>
<p>RemotingXml project was<br />
developed with 2 purposes in mind:</p>
<ul>
<li>            show how to use marshal<br />
by value technology;</li>
<li>             show how to implement a<br />
remote storage.</li>
</ul>
<p>RemotingXml project consists<br />
of a client and a server. The client creates and works with objects and sends them<br />
to the server using marshal-by-value technology to be stored to XML files. The client<br />
is also able to request the objects from the XML files.</p>
<p>This project might be helpful to those, who want to implement some kind of remote<br />
persistence solution. In this example, XML files are used as a very simple and comprehensive<br />
example, however the project can be easily used as a template to build a database<br />
or file-based remoting storage solution.</p>
<h2>Background</h2>
<p>Though marshal-by-reference<br />
remoting is widely covered on the net, marshal-by-value still tends to create some<br />
confusion. This project is created to clear up this confusion and show an example<br />
of how marshal-by-value objects can be used.</p>
<h2>     Solution Organization</h2>
<p>RemotingXml consists of<br />
3 projects:</p>
<ul>
<li>            Server: contains the code<br />
for a remote server. Server project is responsible for creating and starting remoting<br />
services.</li>
<li>             Client: contains the code<br />
for creating persistent classes, sending them for serialization to the server and<br />
requesting the server for objects from the XML files.</li>
<li>           PersistentClasses project<br />
is a library containing the definitions for classes used on the client and on the<br />
server. These include: class to be serialized, list wrapper for the serialized class<br />
and marshal-by-reference class used for persistent classes transport.</li>
</ul>
<h2>         Persistent Classes</h2>
<p>Persistent classes are the<br />
classes that will be created on the client and serialized on the server. Any class<br />
can be persisted if it either has <code>Serializable</code> attribute<br />
or implements <code>ISerializable</code> interface. In this example,<br />
House and Address classes are used.</p>
<p>Address class is saved as<br />
a field in the House class:</p>
<pre>[Serializable]
public class House
{
private Address _address;

private string _owner;
….
}</pre>
<p>In order to save a list of houses we will need to create a special List implementation:</p>
<pre>
[Serializable]

[XmlInclude(typeof(House)), XmlInclude(typeof(Address))]

public class HouseList : List

{

}</pre>
<p>This implementation is required for 2 purposes:<br />
An object passed to a remote server should be serializable<br />
The object need to provide the details of included classes for correct serialization.</p>
<h2>         Transport Class</h2>
<p>In order to send the persistent<br />
classes from the client to the server we will need a Marshal-By-Reference object:</p>
<pre>
    public class XmlHandler: MarshalByRefObject

    {

        private const string Extension = ".xml";

        // list of remote objects

        private IList _persistentObjects;        public IList PersistentObjects

        {

            get { return _persistentObjects; }

            set { _persistentObjects = value; }

        }

        // end PersistentObject

public void StoreData()

        {

            // Serialize object list to xml

            System.Console.WriteLine("persistentObjects " + _persistentObjects.Count);

            if (_persistentObjects.Count &gt; 0)

            {

                // define the object type

                object persistentObject = _persistentObjects[0];

                XmlSerializer serializer = new XmlSerializer(_persistentObjects.GetType());

// delete the old file and create a new one

                string filename = persistentObject.GetType().Name + Extension;

                File.Delete(filename);

                StreamWriter xmlWriter = new StreamWriter(filename);

                // serialize object list

                serializer.Serialize(xmlWriter, _persistentObjects);

                xmlWriter.Close();

            }

        }

        // end StoreData

public IList RetrieveData(Type arrayType, Type objectType)

        {

            // Compose the file name

            string filename = objectType.Name + Extension;

            // deserialize

            XmlSerializer serializer = new XmlSerializer(arrayType);

            FileStream xmlFileStream = new FileStream(filename, FileMode.Open);

            IList objects = (IList)serializer.Deserialize(xmlFileStream);

            xmlFileStream.Close();

            return objects;

        }

        // end RetrieveData

    }</pre>
<p>XmlHandler<br />
holds a reference to the persistent objects array in <code>_persistentObjects</code> variable.<br />
This variable is passed from the client.</p>
<p>As you can see there are methods for serializing and deselializing objects. These<br />
methods are executed on the server.</p>
<h2>         Server</h2>
<p>The Server project is presented<br />
by a single XmlServer class, which role is to start XmlHandler service</p>
<pre>
    class XmlServer

    {

        static void Main(string[] args)

        {

            // Setting up http channel

            HttpChannel channel = new HttpChannel(65101);

            ChannelServices.RegisterChannel(channel);            Type XmlHandler = Type.GetType("RemotingXml.PersistentClasses.XmlHandler, PersistentClasses");

            RemotingConfiguration.RegisterWellKnownServiceType(

                    XmlHandler,

                    "XmlHandlerEndPoint",

                    WellKnownObjectMode.Singleton

                );

            Console.WriteLine("XmlHandler is ready.");

// Keep the server running until the user presses

            // the Enter key.

            Console.WriteLine("Services are running. Press Enter to end...");

            Console.ReadLine();

        }

        // end Main

    }</pre>
<h2>Client</h2>
<p>Client project contains Program class.<span>  </span><br />
In the constructor a connection to the XmlHandler service is established:</p>
<pre>
        public Program()

        {

            string url;            // Setup a client channel to our services.

            HttpChannel channel = new HttpChannel(0);

            url = @"http://LocalHost:65101/";

// Register the channel

            ChannelServices.RegisterChannel(channel, false);

// Set an access to the remote proxy

            xmlHandler = (XmlHandler)RemotingServices.Connect(

                typeof(PersistentClasses.XmlHandler), url + "XmlHandlerEndPoint"

                );

        }

        // end Program</pre>
<p>The RunTest method creates<br />
a list of House objects, sends them to the server using XmlHandler and retrieves<br />
the objects from the XML files on the server:</p>
<pre>
        private void RunTest()

        {

            // an object to be stored remotely

            House house = new House(new Address("East London", "266 Oxford Street"), "Derick Hopkins");

            // Create a list to hold House instances

            HouseList persistentObjects = new HouseList();

            persistentObjects.Add(house);

            // another House for a list

            house = new House(new Address("East London", "23 Stewart Drive"), "Om Henderson");

            persistentObjects.Add(house);

            // Pass House list to the server using XmlHandler

            xmlHandler.PersistentObjects = (IList)persistentObjects;

            // Call method on the server to store houses to an XML file

            xmlHandler.StoreData();

            // Test what is stored to the database

            IList result = xmlHandler.RetrieveData(typeof(HouseList), typeof(House));

            foreach (object obj in result)

            {

                System.Console.WriteLine(obj);

            }

        }

        // end RunTest</pre>
<h2>         Points of Interest</h2>
<p>Creating this project I<br />
had an idea in mind to make it completely generic by using generics for persistent<br />
object collections. However, the idea was not realized due to the fact that Soap<br />
serializer does not support generics and explicit using of binary serializers on<br />
the client and the server still does not solve the problem.</p>
<h2>History</h2>
<p>2007-05-25 First version.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/tetyana.wordpress.com/7/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/tetyana.wordpress.com/7/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tetyana.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tetyana.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tetyana.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tetyana.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tetyana.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tetyana.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tetyana.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tetyana.wordpress.com/7/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tetyana.wordpress.com/7/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tetyana.wordpress.com/7/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=7&subd=tetyana&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://tetyana.wordpress.com/2007/05/25/marshal-by-value-for-persistence/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f46caecbce7147b5aadfc92fc45cc2f5?s=96&#38;d=identicon" medium="image">
			<media:title type="html">tetyana</media:title>
		</media:content>
	</item>
		<item>
		<title>db4o with JasperReports</title>
		<link>http://tetyana.wordpress.com/2007/04/30/db4o-with-jasperreports/</link>
		<comments>http://tetyana.wordpress.com/2007/04/30/db4o-with-jasperreports/#comments</comments>
		<pubDate>Mon, 30 Apr 2007 11:37:55 +0000</pubDate>
		<dc:creator>tetyana</dc:creator>
				<category><![CDATA[JasperReports]]></category>
		<category><![CDATA[db4o]]></category>
		<category><![CDATA[reporting]]></category>

		<guid isPermaLink="false">http://tetyana.wordpress.com/2007/04/30/db4o-with-jasperreports/</guid>
		<description><![CDATA[I&#8217;ve just recently published a short tutorial on db4o + JasperReports here:
Reporting With JasperReports
IMO JasperReports are very suitable for db4o &#8211; did not notice any problems. Want to try it with servlets when I will have some spare time. Hopefully no classloader problems as with BIRT
       <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=6&subd=tetyana&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>I&#8217;ve just recently published a short tutorial on db4o + JasperReports here:</p>
<p><a href="http://developer.db4o.com/Resources/view.aspx/Reference/Implementation_Strategies/Reporting/Reporting_With_JasperReports">Reporting With JasperReports</a></p>
<p>IMO JasperReports are very suitable for db4o &#8211; did not notice any problems. Want to try it with servlets when I will have some spare time. Hopefully no classloader problems as with BIRT</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/tetyana.wordpress.com/6/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/tetyana.wordpress.com/6/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tetyana.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tetyana.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tetyana.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tetyana.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tetyana.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tetyana.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tetyana.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tetyana.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tetyana.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tetyana.wordpress.com/6/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=6&subd=tetyana&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://tetyana.wordpress.com/2007/04/30/db4o-with-jasperreports/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f46caecbce7147b5aadfc92fc45cc2f5?s=96&#38;d=identicon" medium="image">
			<media:title type="html">tetyana</media:title>
		</media:content>
	</item>
		<item>
		<title>Why do I write?</title>
		<link>http://tetyana.wordpress.com/2007/04/18/why-do-i-write/</link>
		<comments>http://tetyana.wordpress.com/2007/04/18/why-do-i-write/#comments</comments>
		<pubDate>Wed, 18 Apr 2007 09:27:03 +0000</pubDate>
		<dc:creator>tetyana</dc:creator>
				<category><![CDATA[technical writer]]></category>

		<guid isPermaLink="false">http://tetyana.wordpress.com/2007/04/18/why-do-i-write/</guid>
		<description><![CDATA[One of my colleagues asked me recently, why having all the programmer&#8217;s experience, do I prefer to work as a technical writer. Well, actually I do quite a lot of programming, I&#8217;d say 80% of my working time.
But getting back to the question: isn&#8217;t programming an expression of your ideas in a structured and defined [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=5&subd=tetyana&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>One of my colleagues asked me recently, why having all the programmer&#8217;s experience, do I prefer to work as a technical writer. Well, actually I do quite a lot of programming, I&#8217;d say 80% of my working time.</p>
<p>But getting back to the question: isn&#8217;t programming an expression of your ideas in a structured and defined way? Nowadays, it is also especially important that the code is beautiful, clean and understandable. So what is the difference from the technical writing?</p>
<p>IMO, the difference is that when your code is done you know if it works, at least to some degree (bugs can pass unknoticed for ages) . When you write documentation &#8211; you have no idea if it works! You&#8217;ve written it up to some degree, as if you were explaining yourself how to do something. But you can&#8217;t even say if it works for yourself. You can only assume that the users will understand your doc and that will be enough for them. Actually you will never know until they will tell you.</p>
<p>That&#8217;s the challenge <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/tetyana.wordpress.com/5/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/tetyana.wordpress.com/5/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tetyana.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tetyana.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tetyana.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tetyana.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tetyana.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tetyana.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tetyana.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tetyana.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tetyana.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tetyana.wordpress.com/5/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=5&subd=tetyana&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://tetyana.wordpress.com/2007/04/18/why-do-i-write/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f46caecbce7147b5aadfc92fc45cc2f5?s=96&#38;d=identicon" medium="image">
			<media:title type="html">tetyana</media:title>
		</media:content>
	</item>
		<item>
		<title>How to create a web-site starter kit (Java)</title>
		<link>http://tetyana.wordpress.com/2007/01/03/how-to-create-a-web-site-starter-kit-java/</link>
		<comments>http://tetyana.wordpress.com/2007/01/03/how-to-create-a-web-site-starter-kit-java/#comments</comments>
		<pubDate>Wed, 03 Jan 2007 19:13:47 +0000</pubDate>
		<dc:creator>tetyana</dc:creator>
				<category><![CDATA[Servlet]]></category>
		<category><![CDATA[StarterKit]]></category>

		<guid isPermaLink="false">http://tetyana.wordpress.com/2007/01/03/how-to-create-a-web-site-starter-kit-java/</guid>
		<description><![CDATA[What Is a Starter Kit?
Starter Kit is the easiest way to start using a new technology. Basically, it is a template project with a comprehensive documentation on where the project can be applied, which functionality is included and how to extend the template with your own functionality.
In this article we will go through a creation [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=4&subd=tetyana&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><h2>What Is a Starter Kit?</h2>
<p class="MsoNormal">Starter Kit is the easiest way to start using a new technology. Basically, it is a template project with a comprehensive documentation on where the project can be applied, which functionality is included and how to extend the template with your own functionality.</p>
<p class="MsoNormal">In this article we will go through a creation of your own StarterKit for a Servlet database application.</p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<h2>Project Structure</h2>
<p class="MsoNormal">Create a simple java project in your development environment.</p>
<p class="MsoNormal">For example you can use the following structure:</p>
<p class="MsoNormal">src – directory for your source code packages</p>
<p class="MsoNormal">doc – documentation for the StarterKit</p>
<p class="MsoNormal">META-INF:</p>
<p class="MsoNormal" style="text-indent:0.5in;">manifest.mf</p>
<p class="MsoNormal">WEB-INF:</p>
<p class="MsoNormal">    <span></span>        classes – compiled application classes</p>
<p class="MsoNormal"><span>            </span>            lib – required libraries</p>
<p class="MsoNormal"><span>            </span>            web.xml – configuration</p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<h2>Source Code</h2>
<p class="MsoNormal">It is recommended to separate database logic from the front-end. For example, you can use com.yourpackage package for your servlet class source and com.yourpackage.data for a data-aware module.</p>
<p class="MsoNormal">In the servlet you can predefine some html code for the page layout, for example:</p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;color:black;"><span>        </span>PrintWriter out = response.getWriter();</span><span style="font-size:9pt;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;color:black;"><span>        </span>response.setContentType(</span><span style="font-size:9pt;color:#2a00ff;">&#8220;text/html&#8221;</span><span style="font-size:9pt;color:black;">);</span><span style="font-size:9pt;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;"><!--[if !supportEmptyParas]--> <!--[endif]--></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;color:black;"><span>        </span>out .println(</span><span style="font-size:9pt;color:#2a00ff;">&#8220;&lt;!DOCTYPE HTML PUBLIC \&#8221;-//W3C//DTD HTML 4.01 Transitional//EN\&#8221; \&#8221;http://www.w3.org/TR/html4/loose.dtd\&#8221;&gt;&#8221;</span><span style="font-size:9pt;color:black;">);</span><span style="font-size:9pt;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;color:black;"><span>        </span>out.println(</span><span style="font-size:9pt;color:#2a00ff;">&#8220;&lt;html&gt;&#8221;</span><span style="font-size:9pt;color:black;"> );</span><span style="font-size:9pt;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;color:black;"><span>        </span>out.println(</span><span style="font-size:9pt;color:#2a00ff;">&#8220;&lt;body&gt;&#8221;</span><span style="font-size:9pt;color:black;">);</span><span style="font-size:9pt;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;"><!--[if !supportEmptyParas]--> <!--[endif]--></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;color:black;"><span>        </span>getDatabaseData();</span><span style="font-size:9pt;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;"><!--[if !supportEmptyParas]--> <!--[endif]--></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;color:black;"><span>        </span>out.println(</span><span style="font-size:9pt;color:#2a00ff;">&#8220;&lt;/body&gt;&#8221;</span><span style="font-size:9pt;color:black;">);</span><span style="font-size:9pt;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;color:black;"><span>        </span>out.println(</span><span style="font-size:9pt;color:#2a00ff;">&#8220;&lt;/html&gt;&#8221;</span><span style="font-size:9pt;color:black;">);</span><span style="font-size:9pt;"></span></p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<p class="MsoNormal"><span style="font-size:9pt;color:black;">getDatabaseData</span> is a function, which will get data from the database module and publish it on the webpage. For a template project <span style="font-size:9pt;color:black;">getDatabaseData() </span><span style="color:black;">function should stay empty – this is the user responsibility to decide on the layout of the page, depending on his application requirements. To make this obvious – add an explicit comment inside the function template.</span><span style="font-size:9pt;color:black;"></span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:black;"><!--[if !supportEmptyParas]--> <!--[endif]--></span></p>
<p class="MsoBodyText">com.yourpackage.data package can be used for your database-handling module. The responsibilities of the module are:</p>
<p class="MsoNormal" style="margin-left:0.5in;text-indent:-0.25in;"><!--[if !supportLists]--><span>-<span>          </span></span><!--[endif]-->set up a database connection</p>
<p class="MsoNormal" style="margin-left:0.5in;text-indent:-0.25in;"><!--[if !supportLists]--><span>-<span>          </span></span><!--[endif]-->provide an easy API to get database data</p>
<p class="MsoNormal" style="margin-left:0.5in;text-indent:-0.25in;"><!--[if !supportLists]--><span>-<span>          </span></span><!--[endif]-->close the connection on application termination</p>
<p class="MsoNormal">You can use pooling and create connection pool in ServletContextListener#contextInitialized event handler. The pool will have to be destroyed in ServletContextListener#contextDestroyed. Otherwise you may want to set up a new connection for each session using sessionCreated and sessionDestroyed events of HttpSessionListener. Note that sessionDestroyed event is only fired if the session expires, so it may be a better idea to close the connection explicitly.</p>
<p class="MsoNormal">ServletContextListener and HttpSessionListener classes should be defined in web.xml if used.</p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<h2>Documentation</h2>
<p class="MsoNormal">To make the template project a StarterKit we will need to add documentation. A general project description and goal can be placed into index.html in the root directory. This will ensure that the user can easily find the documentation when the StarterKit is deployed.</p>
<p class="MsoNormal">More specific documentation, explaining how to create a sample application using the StarterKit can be placed into the doc folder.</p>
<p class="MsoNormal">The ready StarterKit can be packaged into a war file for easy deployment.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/tetyana.wordpress.com/4/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/tetyana.wordpress.com/4/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tetyana.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tetyana.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tetyana.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tetyana.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tetyana.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tetyana.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tetyana.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tetyana.wordpress.com/4/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tetyana.wordpress.com/4/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tetyana.wordpress.com/4/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=4&subd=tetyana&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://tetyana.wordpress.com/2007/01/03/how-to-create-a-web-site-starter-kit-java/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f46caecbce7147b5aadfc92fc45cc2f5?s=96&#38;d=identicon" medium="image">
			<media:title type="html">tetyana</media:title>
		</media:content>
	</item>
		<item>
		<title>Using Mobilink in a Production Environment</title>
		<link>http://tetyana.wordpress.com/2006/12/05/using-mobilink-in-production-environment/</link>
		<comments>http://tetyana.wordpress.com/2006/12/05/using-mobilink-in-production-environment/#comments</comments>
		<pubDate>Tue, 05 Dec 2006 14:06:59 +0000</pubDate>
		<dc:creator>tetyana</dc:creator>
				<category><![CDATA[Mobilink]]></category>
		<category><![CDATA[Synchronization]]></category>

		<guid isPermaLink="false">http://tetyana.wordpress.com/2006/12/05/using-mobilink-in-production-environment/</guid>
		<description><![CDATA[Default Mobilink synchronization is set to the scenario when the data are downloaded once and stay on the mobile device as long as it is used. The changes from the remote database (the one on the device) are synchronized in upload sessions and the data from the central (consolidated) database are sent to the device [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=3&subd=tetyana&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p class="MsoNormal">Default Mobilink synchronization is set to the scenario when the data are downloaded once and stay on the mobile device as long as it is used. The changes from the remote database (the one on the device) are synchronized in upload sessions and the data from the central (consolidated) database are sent to the device in download sessions.</p>
<p class="MsoNormal" style="text-indent:0.5in;">However this mode arises some problematic questions like:</p>
<ul>
<li><!--[if !supportLists]--><span><span></span></span>how to handle multiple users on the same device? Should the data be downloaded for all of them?</li>
<li><!--[if !supportLists]--><span></span>How to backup existing data?</li>
<li><!--[if !supportLists]--><span></span>What to do to make the device failure and database corruption the less painful?<span>  </span></li>
</ul>
<p class="MsoNormal">To solve these problems and make the whole procedure simple the following scenario can be used: the working data is downloaded to the mobile device at the beginning of a shift and uploaded to the central database at the end of a shift (logout). Data should not stay on the device between shifts.</p>
<p class="MsoNormal">This gives us several advantages:</p>
<ul>
<li><!--[if !supportLists]--><span><span></span></span>the data changed at the device won’t be lost in a case of the mobile device hardware failure</li>
<li><!--[if !supportLists]--><span></span>the data will be uploaded from the mobile device in time (outdated data can produce unexpected conflicts in the central database)</li>
<li><!--[if !supportLists]--><span></span>uploading the data together with the logout ensures that only the logged person is responsible for the data uploaded from the device.</li>
</ul>
<p class="MsoNormal" style="margin-left:0.25in;">In such conditions it makes sense:</p>
<ul>
<li><!--[if !supportLists]--><span><span></span></span><!--[endif]-->to start the day with the download synchronization (remote database is empty and filled with the data prepared on the consolidated side)</li>
<li><!--[if !supportLists]--><span></span>to perform full synchronizations during the day if necessary</li>
<li><!--[if !supportLists]--><span></span>to use upload synchronization at the end of a shift (logout), and truncate all the tables after the synchronization was successfully finished.</li>
</ul>
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<h2>Download synchronization</h2>
<p class="MsoNormal">In general case of continuous synchronization download synchronization should know, which rows to download to remote database (so that the same row is not downloaded if it already exists on remote side). Last_download parameter of download_cursor and download_delete_cursor event can be used to distinguish the rows that were updated since the last synchronization. Obviously in this case all the tables, which are supposed to be downloaded, should have a timestamp field showing the time, when the row was updated last. This might be quite undesirable, as it affects the database model.</p>
<p class="MsoNormal">The solution of cleaning remote database before downloading new data gives you a possibility to avoid this problem. On the other side it will have a performance impact of downloading the whole work database before each shift. So this solution can be used if the time available to prepare the remote database for the shift is enough for complete database download.</p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--></p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<h2>Upload synchronization</h2>
<p class="MsoNormal">Mobilink upload implementation is based on the log file that ASA database can create, keeping track of all the changes done to it. Actually database log is a packed SQL command file. It can be easily translated into SQL command sequence using</p>
<p class="MsoNormal" style="text-align:left;" align="left"><strong><span style="font-size:9pt;"><!--[if !supportEmptyParas]--> </span></strong></p>
<p class="MsoNormal" style="text-align:left;" align="left"> <strong><em><span>dbtran </span></em></strong><em><span>[ options transaction-log [ SQL-file ]</span></em></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:9pt;"><!--[if !supportEmptyParas]--> </span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span>For more information see “</span><span>The Log Translation utility”</span><span> from “Adaptive Server Anywhere Database Administration Guide”</span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span><!--[if !supportEmptyParas]--> <!--[endif]--></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span>Obviously the log gives a full and handy information about the changes occurred in the database. Before synchronizing mobilink client (dbmlsync) scans through the database log to collect the changes.</span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span><!--[if !supportEmptyParas]--> <!--[endif]--></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span>Dealing with mobile devices, which have limited storage resources, you might be interested, how to prevent log file from growing eternally. Here ASA provides a special option</span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span><em><strong>dbmlsync</strong> -x</em></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span>Which automatically truncates the log file after successful synchronization. Unfortunately truncating the log it creates its backup, which will still occupy some space and should be deleted intelligently when the updates from it are synchronized to the consolidated database.</span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span><!--[if !supportEmptyParas]--> <!--[endif]--></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span>You can use <em><strong>dbtran</strong> [logfile] –y NULL</em> utility to find out start and end offsets. And you can use </span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span><!--[if !supportEmptyParas]--> </span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><em><span>select first progress from sys.syssync where progress is not null order by progress asc;</span></em></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span><!--[if !supportEmptyParas]--> </span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span>to find the lowest unsynchronized offset.</span></p>
<p class="MsoNormal"><span><!--[if !supportEmptyParas]--> <!--[endif]--></span></p>
<p class="MsoNormal"><span>An alternative approach (and simpler one as well) is to truncate the log file after the data is successfully uploaded to the consolidated database. In this case we will also have to clean synchronization offsets from the remote database. The easiest way to do this is to delete synchronization subscription:</span></p>
<p class="MsoNormal"><span>DROP SYNCHRONIZATION SUBSCRIPTION TO &#8220;MY_PUBLICATION&#8221; FOR &#8220;USER”;</span></p>
<p class="MsoNormal"><span>Don’t forget to recreate it for the following synchronizations.</span></p>
<p class="MsoNormal"><span>Note:</span></p>
<p class="MsoNormal"><span>Information about mobilink users and their subscriptions is kept in sys.syssync table in remote database.</span></p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--></p>
<p class="MsoNormal">You will also have to delete synchronization offset from the consolidated database. The best place to do that is end_synchronization event handler. You can call the following procedure to fulfill the task:</p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;"><!--[if !supportEmptyParas]--> </span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">CREATE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">OR</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">REPLACE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">PROCEDURE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:olive;">End_Sync</span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:black;">ML_USER </span><span style="font-size:8pt;color:#0000f0;">IN</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;">SYNC_OK </span><span style="font-size:8pt;color:#0000f0;">IN</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:red;">NUMBER</span><span style="font-size:8pt;color:#0000f0;">)</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">AS</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">BEGIN</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span></span><span style="font-size:8pt;color:#0000f0;">DELETE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">FROM</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:olive;">ML_SUBSCRIPTION</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">WHERE</span><span style="font-size:8pt;color:black;"> USER_ID </span><span style="font-size:8pt;color:#0000f0;">=</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">(SELECT</span><span style="font-size:8pt;color:black;"> USER_ID </span><span style="font-size:8pt;color:#0000f0;">FROM</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:olive;">ML_USER</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">WHERE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">NAME</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">=</span><span style="font-size:8pt;color:black;"> ML_USER</span><span style="font-size:8pt;color:#0000f0;">);</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span></span><span style="font-size:8pt;color:#0000f0;">COMMIT;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">END;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-indent:0.5in;"><!--[if !supportEmptyParas]--><br />
Truncating the log makes Mobilink see the database as unchanged. Even if the data is different from the consolidated database you can’t synchronize these changes using Mobilink technology. So it is very important to check that the synchronization was successful before truncating the log.</p>
<p class="MsoNormal" style="text-indent:0.5in;"><!--[if !supportEmptyParas]--> <!--[endif]--><br />
<span style="font-size:9pt;font-family:Arial;color:#3366ff;">rc = pb_run_dbmlsync(exe_name, is_publication_name, is_mluser, is_mlpassword, connect_string, other_arguments, is_sync_class_name )</span></p>
<p class="MsoNormal" style="text-indent:0.5in;"><!--[if !supportEmptyParas]--></p>
<p class="MsoNormal" style="text-indent:0.5in;"> rc value should be 0 for successful synchronization.<br />
<span style="font-size:9pt;color:#3366ff;">//check if it finished without mistakes<br />
if (IsNull(rc) = true) then</span></p>
<p class="MsoNormal" style="text-indent:0.5in;"><span style="font-size:9pt;color:#3366ff;"><span></span>return -100<br />
elseif ( rc = 0) then<br />
<span>                </span>// sometimes Status is wrong but sync exits without error<br />
<span>                </span>if (Pos(w_xstratamobile_sync.mle_status.Text, &#8220;Status = 6&#8243;) &lt;&gt; 0 &amp;<br />
<span>                </span>OR Pos(w_xstratamobile_sync.mle_status.Text, &#8220;Status = 1&#8243;)&lt;&gt; 0) then<br />
<span>                </span><span>                </span>rc = 2<br />
<span>                </span><span>                </span>return rc<br />
<span>                </span>end if<span>      </span><br />
else<br />
<span>                </span>return rc<br />
end if</span></p>
<p class="MsoNormal" style="text-indent:0.5in;"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<h2>Authenticating Users</h2>
<p class="MsoNormal">In production environment it is very important to ensure that the person using the mobile application is authenticated. This will prevent data corruption by unauthorized users.</p>
<p class="MsoNormal">In fact 2 different authentication systems are needed:</p>
<ul>
<li><!--[if !supportLists]--><span><span> </span></span><!--[endif]-->mobilink access system</li>
<li><!--[if !supportLists]--><span></span>system access system.</li>
</ul>
<p class="MsoNormal"><span></span>Actually they can be combined, so that the user having the right to synchronize will also have the right to use the system.</p>
<p class="MsoNormal">The authentication system should be flexible and easily manageable. Obviously the best solution is to keep and manage this information in consolidated database. It is fairly easy to accomplish for the system access system. The authentication information can be kept in consolidated database and downloaded to the remote database during synchronization.</p>
<p class="MsoNormal"><span></span>It is more difficult to manage mobilink access information from the central database.</p>
<p class="MsoNormal">One solution is to introduce unauthorized synchronization, which will download mobilink authentication information to the remote database.</p>
<p class="MsoNormal">Another way to do that is to set mobilink users manually on each device (using registry storage or device id).</p>
<p class="MsoNormal">However for both these solutions we should remember that mobilink user becomes a part of the remote database, so if we do not want to generate all the possible mobilink users in the distribution database and replace the database each time the change to the mobilink authentication information occurs, we will need to generate them dynamically.</p>
<p class="MsoNormal">This can be done just before the download synchronization (user name and password should be supplied by user on authentication stage or should be taken from the device information – registry or device id):</p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<p class="MsoNormal">&nbsp;</p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">long l_ret = 0</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">string s_Aux</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">s_Aux = &#8216;CREATE SYNCHRONIZATION USER &#8220;&#8216; +s_User +&#8217;&#8221;&#8216;</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">EXECUTE IMMEDIATE :s_Aux using SQLCA;</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">if (SQLCA.sqlcode &lt;&gt; 0) then</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;"><span>                </span>MessageBox(&#8220;Error&#8221;,&#8221;Unable to create synchroniation user&#8221;)</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;"><span>                </span>ROLLBACK using SQLCA;</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;"><span>                </span>return -1</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">end if</span></p>
<p><span style="font-size:9pt;color:#3366ff;">s_Aux = &#8216;CREATE SYNCHRONIZATION SUBSCRIPTION TO &#8220;MY_PUBLICATION&#8221; FOR &#8220;&#8216;+ s_User +&#8217;&#8221; TYPE TCPIP&#8217;</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">EXECUTE IMMEDIATE :s_Aux using SQLCA;</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">if (SQLCA.sqlcode &lt;&gt; 0) then</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;"><span>                </span>MessageBox(&#8220;Error&#8221;,&#8221;Unable to create subscription&#8221;)</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;"><span>                </span>ROLLBACK using SQLCA;</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;"><span>                </span>return -1</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">end if</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">COMMIT USING SQLCA;</span></p>
<p><span style="font-size:9pt;color:#3366ff;">return l_Ret</span></p>
<p class="MsoNormal">In order to keep database clean the user should be deleted after upload synchronization:</p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">s_Aux = &#8216;DROP SYNCHRONIZATION SUBSCRIPTION TO &#8220;MY_PUBLICATION&#8221; FOR &#8220;&#8216; + s_User + &#8216;&#8221;&#8216;</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">EXECUTE IMMEDIATE :s_Aux using SQLCA; </span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">if (SQLCA.sqlcode &lt;&gt; 0) then</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;"><span>                </span>MessageBox(&#8220;Error&#8221;,SQLCA.sqlerrtext)</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;"><span>                </span>return -1</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">end if</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;"><!--[if !supportEmptyParas]--> <!--[endif]--></span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">s_Aux = &#8216;DROP SYNCHRONIZATION USER &#8220;&#8216; + s_User + &#8216;&#8221;&#8216;</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">EXECUTE IMMEDIATE :s_Aux using SQLCA; </span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">if (SQLCA.sqlcode &lt;&gt; 0) then</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;"><span>                </span>MessageBox(&#8220;Error&#8221;,SQLCA.sqlerrtext)</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;"><span>                </span>return -1</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">end if</span></p>
<p class="MsoNormal"><span style="font-size:9pt;color:#3366ff;">COMMIT USING SQLCA;</span></p>
<p class="MsoNormal">Note: the examples above also take care of creating and deleting of synchronization subscription, which is necessary for maintaining database log (see previous chapter).</p>
<h2>Handling Errors</h2>
<p class="MsoNormal">Mobilink provides 2 different events for error-handling:</p>
<ul>
<li><!--[if !supportLists]--><span><span></span></span><!--[endif]-->handle_error (is triggered by all SQL errors)</li>
<li><!--[if !supportLists]--><span></span>handle_odbc_error (is triggered by ODBC driver errors)</li>
</ul>
<p class="MsoNormal" style="margin-left:0.25in;">Both events provide action_code parameter which can be used to control the behavior after the error occurred:</p>
<p class="MsoNormal" style="margin-left:0.25in;"><!--[if !supportEmptyParas]--></p>
<ul>
<li><!--[if !supportLists]--><span></span><strong><span>1000 </span></strong><span>Skip the current row and continue processing.</span></li>
<li><!--[if !supportLists]--><span></span><strong><span>3000 </span></strong><span>Rollback the current transaction and cancel the current synchronization. This is the default action code, and is used when no handle error script is defined or this script causes an error.</span></li>
<li><!--[if !supportLists]--><span></span><strong><span>4000 </span></strong><span>Rollback the current transaction, cancel the synchronization, and shut down the MobiLink synchronization server.</span></li>
</ul>
<p class="MsoNormal" style="text-indent:0.25in;">If your event handler does not change the action_code it will have the default value – 3000</p>
<p class="MsoNormal" style="text-indent:0.25in;">Typical usage of event handling scripts is logging errors:</p>
<p class="MsoNormal" style="text-indent:0.25in;"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<p class="MsoNormal" style="text-align:left;" align="left">&nbsp;</p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">CREATE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">OR</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">REPLACE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">PROCEDURE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:olive;">Ml_Handle_Error</span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:black;"> n_IN_ACTION_CDE<span>  </span></span><span style="font-size:8pt;color:#0000f0;">IN</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">OUT</span><span style="font-size:8pt;color:black;"><span>  </span></span><span style="font-size:8pt;color:red;">NUMERIC</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>n_ERR_CODE<span>              </span></span><span style="font-size:8pt;color:red;">NUMERIC</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>S_ERR_MESSAGE<span>      </span></span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>S_ML_USERNAME<span>      </span></span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>S_ML_TABLE<span>              </span></span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span> </span></span><span style="font-size:8pt;color:#0000f0;">)</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">AS</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><!--[if !supportEmptyParas]--> <!--[endif]--></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">BEGIN</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>     </span></span><span style="font-size:8pt;color:#0000f0;">DECLARE</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>DT_GENDATE </span><span style="font-size:8pt;color:red;">DATE</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>N_OUT_ACTION_CDE </span><span style="font-size:8pt;color:red;">NUMERIC</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span></span><span style="font-size:8pt;color:#0000f0;">BEGIN</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>   </span></span><span style="font-size:8pt;color:#0000f0;">SELECT</span><span style="font-size:8pt;color:black;"><span>  </span>SYSDATE </span><span style="font-size:8pt;color:#0000f0;">INTO</span><span style="font-size:8pt;color:black;"> DT_GENDATE </span><span style="font-size:8pt;color:#0000f0;">FROM</span><span style="font-size:8pt;color:black;"> DUAL</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>   </span>N_OUT_ACTION_CDE </span><span style="font-size:8pt;color:#0000f0;">:=</span><span style="font-size:8pt;color:black;"> N_IN_ACTION_CDE</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>   </span></span><span style="font-size:8pt;color:#0000f0;">INSERT</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">INTO</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:olive;">ML_ERRORS</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:black;"> IN_ACTION_CDE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>OUT_ACTION_CDE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>ERR_CODE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>ERR_TYPE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> ERR_MESSAGE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>                                                      </span>ML_USERNAME</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span></span><span style="font-size:8pt;color:olive;">ML_TABLE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>GEN_DATE</span><span style="font-size:8pt;color:#0000f0;">)</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>   </span></span><span style="font-size:8pt;color:#0000f0;">VALUES</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>                               </span><span>                      </span></span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:black;">N_IN_ACTION_CDE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>N_OUT_ACTION_CDE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>N_ERR_CODE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:red;">&#8216;SQL&#8217;</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>S_ERR_MESSAGE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>                                                      </span>S_ML_USERNAME</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>S_ML_TABLE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>DT_GENDATE</span><span style="font-size:8pt;color:#0000f0;">);</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span></span><span style="font-size:8pt;color:#0000f0;">COMMIT;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span> </span></span><span style="font-size:8pt;color:#0000f0;">END;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">END;</span><span style="font-size:8pt;color:black;"></span></p>
<p>And for ODBC errors:</p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">CREATE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">OR</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">REPLACE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">PROCEDURE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:olive;">Ml_Handle_Odbc_Error</span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:black;"> n_IN_ACTION_CDE<span>  </span></span><span style="font-size:8pt;color:#0000f0;">IN</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">OUT</span><span style="font-size:8pt;color:black;"><span>  </span></span><span style="font-size:8pt;color:red;">NUMERIC</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>s_ODBC_STATE<span>              </span></span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>S_ERR_MESSAGE<span>      </span></span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>S_ML_USERNAME<span>      </span></span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>S_ML_TABLE<span>              </span></span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span> </span></span><span style="font-size:8pt;color:#0000f0;">)</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">AS</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><!--[if !supportEmptyParas]--> <!--[endif]--></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">BEGIN</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>     </span></span><span style="font-size:8pt;color:#0000f0;">DECLARE</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>DT_GENDATE </span><span style="font-size:8pt;color:red;">DATE</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>N_OUT_ACTION_CDE </span><span style="font-size:8pt;color:red;">NUMERIC</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span></span><span style="font-size:8pt;color:#0000f0;">BEGIN</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>   </span></span><span style="font-size:8pt;color:#0000f0;">SELECT</span><span style="font-size:8pt;color:black;"><span>  </span>SYSDATE </span><span style="font-size:8pt;color:#0000f0;">INTO</span><span style="font-size:8pt;color:black;"> DT_GENDATE </span><span style="font-size:8pt;color:#0000f0;">FROM</span><span style="font-size:8pt;color:black;"> DUAL</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>   </span>N_OUT_ACTION_CDE </span><span style="font-size:8pt;color:#0000f0;">:=</span><span style="font-size:8pt;color:black;"> N_IN_ACTION_CDE</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>   </span></span><span style="font-size:8pt;color:#0000f0;">INSERT</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">INTO</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:olive;">ML_ERRORS</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:black;"> IN_ACTION_CDE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>OUT_ACTION_CDE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> ERR_TYPE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> ERR_MESSAGE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>                                                      </span>ML_USERNAME</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span></span><span style="font-size:8pt;color:olive;">ML_TABLE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>GEN_DATE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> ODBC_STATE</span><span style="font-size:8pt;color:#0000f0;">)</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>   </span></span><span style="font-size:8pt;color:#0000f0;">VALUES</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>                                                     </span></span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:black;">N_IN_ACTION_CDE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>N_OUT_ACTION_CDE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:red;">&#8216;ODBC&#8217;</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> S_ERR_MESSAGE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>                                                      </span>S_ML_USERNAME</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>S_ML_TABLE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"><span>  </span>DT_GENDATE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> s_ODBC_STATE</span><span style="font-size:8pt;color:#0000f0;">);</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span></span><span style="font-size:8pt;color:#0000f0;">COMMIT;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span> </span></span><span style="font-size:8pt;color:#0000f0;">END;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal"><span style="font-size:8pt;color:#0000f0;">END;</span></p>
<p class="MsoNormal" style="text-align:left;" align="left"> <span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-indent:0.25in;">You can also use the event handler to skip some errors silently – for example you can skip SQL errors for duplicates on primary key, when users create the same value independently, but there is no risk of loosing data selecting any of the created values arbitrarily.</p>
<p class="MsoNormal" style="text-indent:0.25in;">Note: the syntax of the error handler script call in ML_SCRIPT :</p>
<p class="MsoNormal"><em><strong>{</strong> call ml_handle_error(?,?,?,?,?)<strong>}</strong></em></p>
<p class="MsoNormal">The curly brackets are mandatory in this call.</p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<p class="MsoNormal">handle_error and handle_odbc_error can catch only part of mobilink errors. For example they won’t catch errors caused by connection problems.</p>
<p class="MsoNormal">For general synchronization errors you can use the error status, which is sent to end_synchronization event:</p>
<p class="MsoNormal">End_synchronization(ml_username, sync_ok)</p>
<p class="MsoNormal">Where sync_ok is 1 for successful synchronization and 0 otherwise.</p>
<p class="MsoNormal">In order to track failed syncs from the central database we can create a special table. For example:</p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">CREATE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">TABLE</span><span style="font-size:8pt;color:black;"> P</span><span style="font-size:8pt;color:olive;">DA_SYNC_HIST</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>PDA_SYNC_DATE<span>             </span></span><span style="font-size:8pt;color:red;">DATE</span><span style="font-size:8pt;color:black;"><span>                                       </span></span><span style="font-size:8pt;color:#0000f0;">NOT</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">NULL,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>USER_ID<span>                          </span></span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:maroon;">20</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">BYTE)</span><span style="font-size:8pt;color:black;"><span>            </span></span><span style="font-size:8pt;color:#0000f0;">NOT</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">NULL,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>PDA_SYNC_COMMENT<span>    </span></span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:maroon;">100</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">BYTE),</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>PDA_SYNC_STATUS<span>       </span></span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:maroon;">20</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">BYTE),</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span>PDA_SYNC_COMPL<span>         </span></span><span style="font-size:8pt;color:red;">DATE</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal"><span style="font-size:8pt;color:#0000f0;">)</span></p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<p class="MsoNormal">Begin and end synchronization events can be used to populate this table:</p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">CREATE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">OR</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">REPLACE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">PROCEDURE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:olive;">Begin_Sync</span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:olive;">ML_USER</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">IN</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:#0000f0;">)</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">AS</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">BEGIN</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">DECLARE</span><span style="font-size:8pt;color:black;"> </span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>        </span>dt </span><span style="font-size:8pt;color:red;">DATE</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>        </span></span><span style="font-size:8pt;color:#0000f0;">BEGIN</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>        </span></span><span style="font-size:8pt;color:#0000f0;">SELECT</span><span style="font-size:8pt;color:black;"><span>  </span>SYSDATE </span><span style="font-size:8pt;color:#0000f0;">INTO</span><span style="font-size:8pt;color:black;"> DT </span><span style="font-size:8pt;color:#0000f0;">FROM</span><span style="font-size:8pt;color:black;"> DUAL</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"> </span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>        </span></span><span style="font-size:8pt;color:#0000f0;">INSERT</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">INTO</span><span style="font-size:8pt;color:black;"> P</span><span style="font-size:8pt;color:olive;">DA_SYNC_HIST</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:black;">PDA_SYNC_DATE</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> USER_ID</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> PDA_SYNC_COMMENT</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> PDA_SYNC_STATUS</span><span style="font-size:8pt;color:#0000f0;">)</span><span style="font-size:8pt;color:black;"> </span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>        </span></span><span style="font-size:8pt;color:#0000f0;">VALUES</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>         </span></span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:black;">DT</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:olive;">ML_USER</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:red;">&#8221;</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:red;">&#8216;BEGIN SYNC&#8217;</span><span style="font-size:8pt;color:#0000f0;">);</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>        </span></span><span style="font-size:8pt;color:#0000f0;">END;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">END;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">/</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal"><!--[if !supportEmptyParas]--> <!--[endif]--></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">CREATE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">OR</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">REPLACE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">PROCEDURE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:olive;">End_Sync</span><span style="font-size:8pt;color:#0000f0;">(</span><span style="font-size:8pt;color:black;">ml_user </span><span style="font-size:8pt;color:#0000f0;">IN</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:red;">VARCHAR2</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;">SYNC_OK </span><span style="font-size:8pt;color:#0000f0;">IN</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:red;">NUMBER</span><span style="font-size:8pt;color:#0000f0;">)</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">AS</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">BEGIN</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span></span><span style="font-size:8pt;color:#0000f0;">DECLARE</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>   </span>DT </span><span style="font-size:8pt;color:red;">DATE</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">BEGIN</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>       </span></span><span style="font-size:8pt;color:#0000f0;">SELECT</span><span style="font-size:8pt;color:black;"><span>  </span>SYSDATE </span><span style="font-size:8pt;color:#0000f0;">INTO</span><span style="font-size:8pt;color:black;"> DT </span><span style="font-size:8pt;color:#0000f0;">FROM</span><span style="font-size:8pt;color:black;"> DUAL</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>       </span></span><em><span style="font-size:8pt;color:green;">&#8211; UPDATE PDA SYNC TABLE</span></em><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>       </span></span><span style="font-size:8pt;color:#0000f0;">IF</span><span style="font-size:8pt;color:black;"> SYNC_OK </span><span style="font-size:8pt;color:#0000f0;">=</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:maroon;">1</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">THEN</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>              </span></span><span style="font-size:8pt;color:#0000f0;">UPDATE</span><span style="font-size:8pt;color:black;"> P</span><span style="font-size:8pt;color:olive;">DA_SYNC_HIST</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">SET</span><span style="font-size:8pt;color:black;"> PDA_SYNC_STATUS </span><span style="font-size:8pt;color:#0000f0;">=</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:red;">&#8216;END SYNC&#8217;</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> PDA_SYNC_COMPL</span><span style="font-size:8pt;color:#0000f0;">=</span><span style="font-size:8pt;color:black;">DT</span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>               </span></span><span style="font-size:8pt;color:#0000f0;">WHERE</span><span style="font-size:8pt;color:black;"> USER_ID</span><span style="font-size:8pt;color:#0000f0;">,</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">=</span><span style="font-size:8pt;color:black;"> ML_USER </span><span style="font-size:8pt;color:#0000f0;">AND</span><span style="font-size:8pt;color:black;"> PDA_SYNC_STATUS </span><span style="font-size:8pt;color:#0000f0;">=</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:red;">&#8216;BEGIN SYNC&#8217;</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>       </span></span><span style="font-size:8pt;color:#0000f0;">ELSE</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>              </span></span><span style="font-size:8pt;color:#0000f0;">UPDATE</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:olive;">PDA_SYNC_HIST</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">SET</span><span style="font-size:8pt;color:black;"><span>  </span>PDA_SYNC_COMMENT </span><span style="font-size:8pt;color:#0000f0;">=</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:red;">&#8216;SYNC ERRORS&#8217;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>               </span></span><span style="font-size:8pt;color:#0000f0;">WHERE</span><span style="font-size:8pt;color:black;"> USER_ID </span><span style="font-size:8pt;color:#0000f0;">=</span><span style="font-size:8pt;color:black;"> ML_USER </span><span style="font-size:8pt;color:#0000f0;">AND</span><span style="font-size:8pt;color:black;"> PDA_SYNC_STATUS </span><span style="font-size:8pt;color:#0000f0;">=</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:red;">&#8216;BEGIN SYNC&#8217;</span><span style="font-size:8pt;color:#0000f0;">;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>       </span></span><span style="font-size:8pt;color:#0000f0;">END</span><span style="font-size:8pt;color:black;"> </span><span style="font-size:8pt;color:#0000f0;">IF;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span>  </span></span><span style="font-size:8pt;color:#0000f0;">COMMIT;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:black;"><span> </span></span><span style="font-size:8pt;color:#0000f0;">END;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">END;</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal" style="text-align:left;" align="left"><span style="font-size:8pt;color:#0000f0;">/</span><span style="font-size:8pt;color:black;"></span></p>
<p class="MsoNormal">These procedures do not ensure exact synchronization tracking: End_Sync will close all the open synchronizations. But actually that is enough as the integrity of synchronizations is ensured by Mobilink itself.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/tetyana.wordpress.com/3/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/tetyana.wordpress.com/3/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/tetyana.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/tetyana.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/tetyana.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/tetyana.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/tetyana.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/tetyana.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/tetyana.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/tetyana.wordpress.com/3/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/tetyana.wordpress.com/3/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/tetyana.wordpress.com/3/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=tetyana.wordpress.com&blog=584333&post=3&subd=tetyana&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://tetyana.wordpress.com/2006/12/05/using-mobilink-in-production-environment/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f46caecbce7147b5aadfc92fc45cc2f5?s=96&#38;d=identicon" medium="image">
			<media:title type="html">tetyana</media:title>
		</media:content>
	</item>
	</channel>
</rss>