<?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/"
	>

<channel>
	<title>Terminal.app &#187; WebObjects</title>
	<atom:link href="http://terminalapp.net/category/webobjects/feed/" rel="self" type="application/rss+xml" />
	<link>http://terminalapp.net</link>
	<description>And the Cosmic AC said, &#34;LET THERE BE LIGHT!&#34; And there was light.</description>
	<lastBuildDate>Wed, 20 Oct 2010 21:58:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>RESTNotes code sample</title>
		<link>http://terminalapp.net/restnotes-code-sample/</link>
		<comments>http://terminalapp.net/restnotes-code-sample/#comments</comments>
		<pubDate>Fri, 08 Oct 2010 16:55:09 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/?p=347</guid>
		<description><![CDATA[A few days ago I released RESTNotes. RESTNotes is a code sample package of a distributed notes application. It consists of an iPhone application that stores all its data in an WebObjects server app. Communication is done using REST style &#8230; <a href="http://terminalapp.net/restnotes-code-sample/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A few days ago I released RESTNotes. RESTNotes is a code sample package of a distributed notes application. It consists of an iPhone application that stores all its data in an WebObjects server app. Communication is done using REST style techniques.</p>
<p>I&#8217;ve done this to learn about REST, and get the feeling of how should things be made, what problems would I find, and so on. I spent some time creating an easy-to-use methodology on the iPhone side, making the communication APIs simple but flexible. Also, I looked at problems like authentication and error reporting.</p>
<p>If you&#8217;re interested, <a href="http://code.google.com/p/rest-notes/source/checkout">the source is published</a> on Google Code, together with some <a href="http://code.google.com/p/rest-notes/wiki/Introduction">nice documentation</a> on the project wiki, explaining the general architecture of the client and solutions to some of the problems I found. Hope you find it useful. :)</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/restnotes-code-sample/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WebObjects, PostgreSQL and DB growing, and growing, and growing…</title>
		<link>http://terminalapp.net/webobjects-postgresql-and-db-growing-and-growing/</link>
		<comments>http://terminalapp.net/webobjects-postgresql-and-db-growing-and-growing/#comments</comments>
		<pubDate>Sun, 12 Jul 2009 22:20:46 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/?p=112</guid>
		<description><![CDATA[One of the databases that support our application has some tables where data is updated very frequently. In PostgreSQL world, this means the table must be vacuumed very frequently to remove the old versions of the updated rows, clearing up &#8230; <a href="http://terminalapp.net/webobjects-postgresql-and-db-growing-and-growing/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of the databases that support our application has some tables where data is updated very frequently. In PostgreSQL world, this means the table must be vacuumed very frequently to remove the old versions of the updated rows, clearing up space for new rows or new versions of existing rows. On very frequently updated tables, where insertions occur occasionally, but updates very often (several per second), recent versions of PostgreSQL should trigger their auto-vacuum daemon at a very high rate, like every 2 or 3 minutes, for those tables.</p>
<p>Despite this, our database kept growing like crazy, with no apparent reason. I decided to investigate what was going on.</p>
<p>The <code>vacuum verbose</code> is a neat command you can use in the PostgreSQL console to check what&#8217;s going on with the built-in cleaning service. This will run a vacuum on every table, giving you extensive report on how many used and unused rows exist in each table, and how many of the unused were deleted and their space reclaimed by PostgsreSQL.</p>
<p>The most interesting output of this command are the lines (one per table) like: <code>DETAIL: 2942 dead row versions cannot be removed yet.</code>. This means you have, in this example, 2942 rows on that table that are not used any more, but for some reason, vacuum was not able to delete them.</p>
<p>Browsing the web, I found out the most probable cause of this issue is the existence of a transaction that started a long time ago, and never finished. PostgreSQL will only delete rows older than the start timestamp of the oldest transaction still running. Newer versions might be needed by those transactions, so they are kept in place, even if their death sentence is already declared.</p>
<p>So, I started looking at what was going on inside the database engine, searching for those pending transactions. A lot of useful information about the current status of a PostgreSQL database can be found in many tables that exist in memory during PostgreSQL execution, that can be queried as any regular table. The one that was important for me was <code>pg_stat_activity</code>, which contains a list of all the current transactions.</p>
<p>By running the <code>select * from pg_stat_activity;</code> SQL command, I saw that each instance of my application had create two database connections, and for each instance, one of the connections had a transaction that started at the time the application instance was launched, but never committed or rolled back.</p>
<p>After some time of poking around, reading code, and talking to the right people, the problem was revealed. By default, WebObjects applications will open two connections to each database they talk to. One for the actual data queries, and the other to ask the database, at startup time, for what&#8217;s called the jdcb2info. This is a bunch of information needed to map between PostgreSQL and Java data types. And, due to one of those very old bugs that strangely nobody fixed yet that make WO fun, the transaction where that information is requested is never committed. So, the transaction will remain open, and PostgreSQL won&#8217;t vacuum a thing until you quit your application.</p>
<p>Although there&#8217;s not yet a solution for the problem itself (hopefully there will be, as I filled a bug in Radar), you can avoid it, by using the jdcb2info bundled in the PostgreSQL plugin instead of requesting it from the DB. To do this, simply append <code>?useBundledJdbcInfo=true</code> to your DB connection URL, like <code>jdbc:postgresql://localhost/dbname?useBundledJdbcInfo=true</code>. This way, the second connection is not created at all, and no pending transaction will occur.</p>
<p>And of course, after doing this, the DB happily vacuumed hundreds of thousands of dead rows and stopped growing like crazy. Also, a tip: if you really need to vacuum the database right now, but you can&#8217;t stop your apps and interrupt service, simply obtain the pids of the PostgreSQL processes that are maintaing the offending connections from the <code> pg_stat_activity</code> table, and kill them, using the unix command <code>kill &lt;pid&gt;</code> command. The connections will die, but your apps will not.</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/webobjects-postgresql-and-db-growing-and-growing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WebObjects, SSL, Apache 2.2, FreeBSD problems</title>
		<link>http://terminalapp.net/webobjects-ssl-apache-22-freebsd-problems/</link>
		<comments>http://terminalapp.net/webobjects-ssl-apache-22-freebsd-problems/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 22:40:01 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/?p=78</guid>
		<description><![CDATA[I still didn&#8217;t have time to investigate this deeply, but here goes anyway, as I didn&#8217;t find the answer to this anywhere. I had the problem described in the Apache 2.2 adaptor: SSL fails on FreeBSD amd64 thread in the &#8230; <a href="http://terminalapp.net/webobjects-ssl-apache-22-freebsd-problems/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I still didn&#8217;t have time to investigate this deeply, but here goes anyway, as I didn&#8217;t find the answer to this anywhere.</p>
<p>I had the problem described in the <a href="http://lists.apple.com/archives/Webobjects-deploy/2007/Jul/msg00000.html">Apache 2.2 adaptor: SSL fails on FreeBSD amd64</a> thread in the <a href="http://lists.apple.com/mailman/listinfo/webobjects-deploy">WebObjects-Deploy mailing list</a>. As the thread suggests, the problem is not related to 64 bits at all, but with a problem related to the SSL client certificate becoming corrupted somewhere between an SSL request entering apache and leaving to the selected WebObjects application instance.</p>
<p>The thread suggests a little hack in the Wonder&#8217;s Adaptor code to ignore the SSL client certificate stuff, but I found that to be a little too dirty. So I dug this as much as time allowed.</p>
<p>I found the adaptor will forward all the SSL http headers it has to the application. This allows the application to analyse the SSL information (like the certificates themselves, the certificate information, etc) if, for some reason, that&#8217;s needed. However, the SSL client certificate information is becoming corrupted, and screws up the request, making it invalid. As the application will not reply to what it believes to be an invalid http request, the adaptor thinks the application is non-responsive, and considers it invalid for some minutes. That&#8217;s why the user starts to get the infamous &#8220;No instance available&#8221; message.</p>
<p>I still don&#8217;t know if this is an Apache, mod_ssl, WO Adaptor or whatever bug. But I know how to work around it, avoiding this error. As the problem is related to providing the SSL information to the adaptor, I chose to simply block it. This can be done in the Apache configuration. Just add this to the right context (usually the SSL virtual host configuration block):</p>
<p><code><br />
SSLOptions -FakeBasicAuth -ExportCertData -StrictRequire -StdEnvVars<br />
</code></p>
<p>This will hide all the SSL information from the adaptor, avoiding the error. I&#8217;ll try to dig this a little more if I have some free time and update this post.</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/webobjects-ssl-apache-22-freebsd-problems/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Apple 2009 wish list</title>
		<link>http://terminalapp.net/apple-2009-wish-list/</link>
		<comments>http://terminalapp.net/apple-2009-wish-list/#comments</comments>
		<pubDate>Fri, 02 Jan 2009 00:31:09 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Generic]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Mac OS X Server]]></category>
		<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/?p=70</guid>
		<description><![CDATA[It&#8217;s a brand new year. So here&#8217;s my wish list for Apple: Please fix the wireless driver that causes my Mac to crash about 10% of the times I turn Airport off. Please fix the trackpad driver, or whatever is &#8230; <a href="http://terminalapp.net/apple-2009-wish-list/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s a brand new year. So here&#8217;s my wish list for Apple:</p>
<ul>
<li>Please fix the wireless driver that causes my Mac to crash about 10% of the times I turn Airport off.</li>
<li>Please fix the trackpad driver, or whatever is causing the trackpad to behave strongly erratic during about 30 seconds after waking the Mac up.</li>
<li>Please fix the damn copy/paste bug that makes the paste command paste the previously copied object and not the most recent one. This is specially irritating when you cut a piece of text, paste and you realize you are pasting something else, and that your supposedly cut piece of text is lost forever, unless you can undo and get it back.</li>
<li>Please fix the irritating bug that causes an iChat window to keep being the active one even after I click Safari, making its window go in front of iChat&#8217;s. That&#8217;s specially annoying when I type apple-W to close the Safari window, and the ichat one goes away.</li>
<li>Please provide replacement keyboards for people who has pre-unibody MacBook Pros that, you know, actually sense a keystroke every time the key goes all the way down, without the need to almost punch the key.</li>
<li>Please fix whatever is causing my father&#8217;s MacBook Pro to keep waking up and going back to sleep when the lid is closed and the charger on, despite I had already turned off every god damn thing that could wake it up, including the lid open event.</li>
<li>Speaking about the charger, please provide chargers where the charge light doesn&#8217;t go off for some unknown reason. It still works, but it doesn&#8217;t inspire a lot of confidence in it ans it&#8217;s safety.</li>
<li>Please provide granular updates to Mac OS X Server. Please please please pretty please.</li>
<li>Please care a little more about the entreprise and IT markets, namely your own web application technology (WebObjects, of course).</li>
</ul>
<p>Thank you, guys! You must hate me but you&#8217;re nice people anyway. Sometimes.</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/apple-2009-wish-list/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Firefox 3 javascript evaluating order problems</title>
		<link>http://terminalapp.net/firefox-3-javascript-evaluating-order-problems/</link>
		<comments>http://terminalapp.net/firefox-3-javascript-evaluating-order-problems/#comments</comments>
		<pubDate>Thu, 31 Jul 2008 21:36:09 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[AJAX and Javascript]]></category>
		<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/?p=46</guid>
		<description><![CDATA[I found out the hard way the recently released third main version of Firefox has a serious issue related to the order in which the Javascript code is executed in a page. The bug is somehow related to the files &#8230; <a href="http://terminalapp.net/firefox-3-javascript-evaluating-order-problems/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I found out the hard way the recently released third main version of Firefox has a serious issue related to the order in which the Javascript code is executed in a page. The bug is somehow related to the files being, or not, cached on the browser.</p>
<p>Wonder Ajax framework adds a lot of Ajax goodies to a standard WebObjects applications. The way a page is built is by placing on the page header all the calls to load Javascript files. There&#8217;s a special case, which is when you need a JSON proxy. That is useful if you need to write more powerful Ajax behaviour than all the component trickery Wonder offers you. The JSON proxy will not only load the necessary Javascript file, but run one code line to create the actual proxy and establish the communication with the server. So the page header will have something that looks more or less like this:</p>
<pre>
&lt;script src="/some/path/prototype.js"&gt;&lt;/script&gt;
&lt;script src="/some/path/effects.js"&gt;&lt;/script&gt;
&lt;script src="/some/path/wonder.js"&gt;&lt;/script&gt;
&lt;script src="/some/path/english.js"&gt;&lt;/script&gt;
&lt;script src="/some/path/combo.js"&gt;&lt;/script&gt;
&lt;script src="/some/path/feedback.js"&gt;&lt;/script&gt;
&lt;script src="/some/path/jsonrpc.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
var jason = new JSONRpcClient("proxyUrl");
&lt;/script&gt;
&lt;script src="/some/path/comboboxes.js"&gt;&lt;/script&gt;
...
</pre>
<p>When the page loads, all those scripts will be loaded and the new JSONRpcClient() method will be executed during the page load, as expected.</p>
<p>The problem starts when you have a javascript method associated with the onLoad window event. This is done by using the onload attribute in the body element:</p>
<pre>
&lt;body onLoad="initPage();"&gt;
</pre>
<p>The onLoad function should be triggered when the page finishes loading. This, implicitly, means that the onLoad will be run only after all the inline javascript code (in the page header or body) be run, because that is still considered to be part of the page loading process. So, in our case, first, load all the JS and create the JSON proxy, and then run the onLoad method.</p>
<p>This works on every browser, and also on Firefox 3 on the first page load. The problem is that most of the subsequent page loads on Firefox 3 won&#8217;t work, at least if your onLoad method depends on the existence of the JSON proxy. For some reason, when Firefox 3 has all the Javascript files already in the local cache, the onLoad event is triggered too soon, namely before the header scripts are executed and the proxy has been created. This will break all your code executed by the onLoad method that assumes the proxy is already ready to work.</p>
<p>I have tried several solutions for this. The only one I had success with is the following. It&#8217;s kind of dirty, but it works. The idea is simple: if the onLoad method is to be executed before the proxy exists, than we wait some miliseconds and try again later until the proxy is ready to be used. So, if your method is like this:</p>
<pre>
function myOnloadMethod() {
  runInitStuff();
}
</pre>
<p>Change it to:</p>
<pre>
function myOnloadMethod() {
  if( window.jason ) {
    runInitStuff();
  } else {
    setTimeout( 'myOnloadMethod();', 10 );
  }
}
</pre>
<p>This will check every 10 milliseconds if the proxy is already there. If it is, your method will be run. If not, it will keep trying.</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/firefox-3-javascript-evaluating-order-problems/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Upgrading Mac OS X Leopard Server</title>
		<link>http://terminalapp.net/upgrading-mac-os-x-leopard-server/</link>
		<comments>http://terminalapp.net/upgrading-mac-os-x-leopard-server/#comments</comments>
		<pubDate>Fri, 11 Jul 2008 23:20:31 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[Mac OS X Server]]></category>
		<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/?p=42</guid>
		<description><![CDATA[I was expecting that. Fortunately, I was ready for it. So, I&#8217;ll describe some details of upgrading Leopard Server from 10.5.2 to 10.5.4 to avoid you the same trouble. If you read my previous article about Leopard Server, you know &#8230; <a href="http://terminalapp.net/upgrading-mac-os-x-leopard-server/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I was expecting that. Fortunately, I was ready for it. So, I&#8217;ll describe some details of upgrading Leopard Server from 10.5.2 to 10.5.4 to avoid you the same trouble.</p>
<p>If you read <a href="http://terminalapp.net/migrating-to-leopard-server/">my previous article about Leopard Server</a>, you know that I had to recompile MySQL, PHP and Apache to PowerPC 32 bits, because I could not use the 64 bits version on our G5 server. The story was a bit complicated, but the idea was that I needed PostgreSQL and MySQL support on PHP. As the MySQL default installation on OS X Server doesn&#8217;t include the shared libraries, I had to recompile MySQL to be able to recompile PHP. But I could not make MySQL compile for 64 bits, so I compiled everything (including Apache) to 32 bits.</p>
<p>So, I was expecting it: as soon as I would upgrade my server, the installers would replace Apache with a more recent version, and it would not start because PHP and MySQL stuff was compiled for 32 bits. And it happened.</p>
<p>How to fix it? Simple. You have to do two things: first, remove the PowerPC 64 part from the httpd binary. Second, recompile your customized version of PHP, because PHP gets replaced too.</p>
<p>To remove the PowerPC 64 part of the binary, you don&#8217;t need to recompile Apache as I did before. There are two very useful commands you can use: file and lipo. If you do the following commands:</p>
<p><code><br />
cd /usr/sbin<br />
file httpd<br />
</code></p>
<p>The result will be:</p>
<p><code><br />
httpd: Mach-O universal binary with 4 architectures<br />
httpd (for architecture ppc7400):	Mach-O executable ppc<br />
httpd (for architecture ppc64):	Mach-O 64-bit executable ppc64<br />
httpd (for architecture i386):	Mach-O executable i386<br />
httpd (for architecture x86_64):	Mach-O 64-bit executable x86_64<br />
</code></p>
<p>As you can see, Apple ships httpd compiled for their four possible architectures. In my case, I want to remove the ppc64 one to force httpd being executed in 32 bits. That&#8217;s where lipo comes in hand:</p>
<p><code><br />
lipo -remove ppc64 -output httpd32 httpd<br />
mv httpd httpd64<br />
mv httpd32 httpd<br />
</code></p>
<p>That&#8217;s it. The ppc64 part of the binary has been removed, and a new binary was created. I then just switch the binaries, and there you go, Apache running on 32 bits mode on PowerPC:</p>
<p><code><br />
httpd32: Mach-O universal binary with 3 architectures<br />
httpd32 (for architecture ppc7400):	Mach-O executable ppc<br />
httpd32 (for architecture i386):	Mach-O executable i386<br />
httpd32 (for architecture x86_64):	Mach-O 64-bit executable x86_64<br />
</code></p>
<p>Then I just needed to recompile PHP and everything was back on track.</p>
<p>Also, be careful because the 10.5.4 update will upgrade WebObjects to 5.4.2. If you are still using WO 5.3 like me, you&#8217;ll have to reinstall 5.3 again, as described in the <a href="http://lists.apple.com/archives/webobjects-dev//2007/Oct/msg00357.html">Mike&#8217;s document</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/upgrading-mac-os-x-leopard-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Back from USA</title>
		<link>http://terminalapp.net/back-from-usa/</link>
		<comments>http://terminalapp.net/back-from-usa/#comments</comments>
		<pubDate>Sun, 15 Jun 2008 23:01:07 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[WebObjects]]></category>
		<category><![CDATA[WOWODC WWDC 2008 WebObjects LEWOStuff Houdah Stanford]]></category>

		<guid isPermaLink="false">http://terminalapp.net/?p=39</guid>
		<description><![CDATA[Well, I&#8217;m back from another WOWODC and WWDC. I&#8217;m still really tired, but some quick notes: As David LeBer already mentioned, Pascal did an amazing job organizing WOWODC all by himself. Great room (a bit cold on the first day &#8230; <a href="http://terminalapp.net/back-from-usa/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Well, I&#8217;m back from another WOWODC and WWDC. I&#8217;m still really tired, but some quick notes:</p>
<ul>
<li>As <a href="http://davidleber.net/?p=319">David LeBer already mentioned</a>, Pascal did an amazing job organizing <a href="http://www.wocommunity.org/wowodc08/">WOWODC</a> all by himself. Great room (a bit cold on the first day ;) ), large windows and sunlight on the halls. Food (well&#8230; not that good, but after all, it&#8217;s USA!) and caffeine provided frequently. Very very nice. Suggestion for the next year: a bigger (and brighter) screen, and eventually plasma screens among the room to make it easy for people in the back to read the code.</li>
<li>I learned a lot about WO frameworks out there (like <a href="http://projectwonder.blogspot.com/">Wonder</a>, <a href="http://code.google.com/p/houdah-webobjects-frameworks/">Houdah</a> and specially <a href="http://homepage.mac.com/andrewlindesay/le/page_lestuff.html">LEWOStuff</a> that I did not know before). I met for the first time some very talented people, and of course, all the folks from the previous conferences. It&#8217;s great to be able to have technical discussions and know different views on the same problems from all those skilled and experienced people out there, face to face.</li>
<li><a href="http://developer.apple.com/wwdc/">WWDC</a> had some interesting news on many stuff. As you know, I cannot talk about the stuff under NDA, so I shall only say that some interesting stuff is being done on the WO side. Also, as you all know by now, the <a href="http://www.apple.com/iphone/">iPhone is now 3G</a>, includes a GPS, the price was slashed, and will be available in many countries of the world. I just hope the service providers slash the data roaming prices, because that makes the iPhone useless when you go to foreign countries. Finally, <a href="http://www.apple.com/macosx/snowleopard/">Snow Leopard</a> was announced, and, as already expected, the focus is not on new features, but on a big cleanup of the OS infrastructure. Not only this are great news for us, developers, but also shows some courage from Apple and a lot of respect for their users. They want to focus the next year on improving the quality of their OS, rather than packing it up with some new features just to win the race against the competition.</li>
<li>As a side note, the <a href="http://www.mactech.com/">MacTech</a> people was giving away some magazines for free to the people who were <a href="http://www.flickr.com/photos/velouriadark/2571799198/">standing</a> <a href="http://www.flickr.com/photos/velouriadark/2570973867/">in line</a> <a href="http://www.flickr.com/photos/velouriadark/2571799478/">during the morning</a>. I took the time to read most of it during my flight, and I really liked it. I was a MacTech subscriber in the past, but I cancelled it because, during my graduation, I didn&#8217;t have time to read it (it&#8217;s good to graduate on a place where you actually don&#8217;t have time to learn, isn&#8217;t it?). Maybe I&#8217;ll subscribe it again now.</li>
<li>Not related to the conferences themselves, we went to visit the bay area surroundings on Friday afternoon. We did the classic trip to the Apple and Google campuses, because we are all geeks, but we also went to the Stanford and Berkeley campuses. The Standford campus totally blow me away. You have to see it to believe it. From now on, I&#8217;ll laugh, really laugh, every time I hear a faculty from my university stating that we actually have a campus. The Berkeley campus did not impress me much. It&#8217;s more urban style, more crowded and dense. I prefer the Stanford way, with space, a huge amount of space, tons and tons of space, really. Almost made me want to return to the univ! :)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/back-from-usa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WWDC and WOWODC 2008</title>
		<link>http://terminalapp.net/wwdc-wowodc-2008/</link>
		<comments>http://terminalapp.net/wwdc-wowodc-2008/#comments</comments>
		<pubDate>Thu, 05 Jun 2008 14:13:54 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[WebObjects]]></category>
		<category><![CDATA[2008]]></category>
		<category><![CDATA[wowodc]]></category>
		<category><![CDATA[wwdc]]></category>

		<guid isPermaLink="false">http://terminalapp.net/?p=38</guid>
		<description><![CDATA[It&#8217;s that time of the year&#8230; packing up to leave tomorrow, as I will attend WOWODC and WWDC 2008 in San Francisco. See you there!]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s that time of the year&#8230; packing up to leave tomorrow, as I will attend <a href="http://www.wocommunity.org/wowodc08/">WOWODC</a> and <a href="http://developer.apple.com/wwdc/">WWDC</a> 2008 in San Francisco. See you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/wwdc-wowodc-2008/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Apple Defines a Product Road Map for WebObjects!</title>
		<link>http://terminalapp.net/apple-defines-a-product-road-map-for-webobjects/</link>
		<comments>http://terminalapp.net/apple-defines-a-product-road-map-for-webobjects/#comments</comments>
		<pubDate>Mon, 28 Apr 2008 21:35:59 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/?p=35</guid>
		<description><![CDATA[In 1997. (Yes, I&#8217;m cleaning up some really old stuff)]]></description>
			<content:encoded><![CDATA[<p>In 1997. (Yes, I&#8217;m cleaning up some really old stuff)</p>
<p><a href='http://terminalapp.net/wp-content/uploads/2008/04/webobjects.jpg'><img src="http://terminalapp.net/wp-content/uploads/2008/04/webobjects-219x300.jpg" alt="" title="Apple Defines a Product Road Map for WebObjects" width="219" height="300" class="aligncenter size-medium wp-image-36" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/apple-defines-a-product-road-map-for-webobjects/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Dr. Optimistic Locking</title>
		<link>http://terminalapp.net/dr-optimistic-locking/</link>
		<comments>http://terminalapp.net/dr-optimistic-locking/#comments</comments>
		<pubDate>Sun, 13 Apr 2008 16:18:35 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/?p=33</guid>
		<description><![CDATA[or How I learned to stop worrying and lock the EOObjectStoreCoordinator So those of you who read the WebObjects Developer mailing list know I&#8217;m a bit obsessed about concurrency issues. Namely concurrent data write operations, specially when you have lots &#8230; <a href="http://terminalapp.net/dr-optimistic-locking/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em>or How I learned to stop worrying and lock the EOObjectStoreCoordinator</em></p>
<p>So those of you who read the <a href="http://lists.apple.com/mailman/listinfo/webobjects-dev">WebObjects Developer mailing list</a> know I&#8217;m a bit obsessed about concurrency issues. Namely concurrent data write operations, specially when you have lots of derived data on the database due to performance issues.</p>
<p>A few months ago, I wrote <a href="http://terminalapp.net/recovering-from-optimistic-locking-exceptions/">an article about handling concurrent data access in WebObjects applications</a> that included a nice solution for the problem. The thing is&#8230; it&#8217;s wrong. It&#8217;s all wrong. It doesn&#8217;t work, in the sense that it won&#8217;t give you any guarantee that you won&#8217;t discard upgrades made by other threads or instances of the application. I have to thank Chuck that looked at the code and said &#8220;doesn&#8217;t work&#8221;. Chuck is right, by definition, so when he says something doesn&#8217;t work, it just doesn&#8217;t. And he was right again.</p>
<p>So, in that article, I avoided the problem created by an editing context delaying the merge of the changes made by other contexts to its objects to the moment when the context is unlocked. But I made a very important mistake: I assumed WebObjects implementation of optimistic locking worked. It doesn&#8217;t. Unfortunately, optimistic locking is broken in WO due to a design flaw.</p>
<p>The problem is simple: you can lock everything you want. You can lock your contexts, you can use classic Java locking, you can do whatever you want. But, as long as you don&#8217;t lock the EOObjectStoreCoordinator, you can&#8217;t trust optimistic locking. Because the row snapshots are unique to a EOF stack, you can have a thread in the middle of a critical part of your code, like I showed on the previous article, and have another thread changing those snapshots simply by doing any operation that brings fresh data from the database, like a fetch specification with the refreshesRefetchedObjects option turned on. Unless you use classic Java locking to lock everything in your code where you might eventually do a <em>refreshing fetch</em> (which is insane), you cannot trust the row snapshots that will be used as a base of comparison for optimistic locking to be unchanged during your code critical segments.</p>
<p>If this sounds too confusing, think in the following example. We have an entity with attribute ATT that we want to increment using optimistic locking. Remember that the ideia is the following: we want to make sure that, if two or more threads increment the value at the same time, only one of the threads will succeed, all the others will receive an optimistic locking exception, and effectively abort the transaction (or repeat it).</p>
<p>So, we have two instances, INST1 and INST2 running. Assume we increment the value inside a method like the one I wrote in the previous article. Let&#8217;s now run some steps:</p>
<ol>
<li>INST2 reads ATT with value = 3. The row snapshot in the INST2 EOF stack has ATT = 3, as expected.</li>
<li>INST1 reads ATT with value = 3. Again, the row snapshot in INST1 EOF stack has ATT = 3.</li>
<li>INST2 increments ATT to 4, and saves the result to the database. It will naturally succeed, updating the DB and it&#8217;s own snapshot to ATT = 4. We can forget INST2 from now on.</li>
<li>INST1, in another thread, runs a fetch specification with refreshesRefetchedObjects on. As the ATT value in the database is now 4, that thread will have ATT = 4 on the editing context that fetched the object, and (here&#8217;s the problem) the row snapshot will be updated to what&#8217;s currently in the database, which is ATT = 4.</li>
<li>INST1, in the original thread, finally increments the value of ATT to 4 (remember, it was 3 on it&#8217;s editing context), and tries to save. It will use the row snapshot do to the optimistic locking comparison. So, what it will do, in a rough translation of SQL, is &#8220;update att to 4 where entityId is some Id and att is <strong><span style="color: #f00;">4</span></strong>&#8220;. The red 4 comes from the row snapshot.</li>
<li>As the value on the database is now 4, the save will succeed. The final value of ATT will be 4 and not 5, as expected after being incremented in both threads.</li>
</ol>
<p>The problem here is the assumption EOF does when saving changes of attributes with optimistic locking enabled. EOF assumes that the row snapshots represent the original status of the objects when they were fetched to the context being saved. So, it compares the current database status with the original status to detect changes. The problem is that assumption is simply not true. There can only be one row snapshot in an EOF stack for a given row, and nothing will guarantee the snapshot doesn&#8217;t change in the middle of the critical section.</p>
<p>Facing this, there&#8217;s only one thing you can do: make that assumption become true. And to do that, you need to either use a different EOF stack per thread (very very high resource consumption, not only in memory but in DB connections too) or use the &#8220;big&#8221; lock in the stack. That big lock is the lock in the EOObjectStoreCoordinator. If you need absolute reliability when managing concurrent data access, you&#8217;ll have to lock EOObjectStoreCoordinator before fetching (and refreshing, of course) the objects you will change and only unlock it after saving those objects. You can do that with code like this:</p>
<pre>
EOObjectStore osc = someEditingContextOnThisThread.rootObjectStore();
try {
  osc.lock();
  // Do as I wrote on the previous article:
  // create a new editing context with fetch timestamp
  // set to "now", fetch all your objects, process them,
  // and try to save them, handling OL exceptions.
} finally {
  osc.unlock();
}
</pre>
<p>Note that I put osc.unlock() call in the &#8220;finally&#8221; segment of the try/catch wrapper. You need to take extra care to make sure that, whatever happens, you will not leave the EOObjectStoreCoordinator locked, or all your application&#8217;s database access will simply be stopped forever.</p>
<p>Of course, there&#8217;s a downside for this solution: while you are processing the objects inside the critical code segment, no other thread will be able to access the database, in read or write mode. I can give you two advices on this.</p>
<p>First, the obvious one: keep that processing as simple and fast as possible. Remember that long operations should be done in background threads with their own EOF stack or, better yet, in separate &#8220;maintenance&#8221; applications. This technique should be used only for fast operations, or the users of your application will get bored waiting.</p>
<p>Second, create multiple EOF stacks (a reasonable amount, like 3 or 4). This will speed up things a bit, because it will reduce the probability of a thread having to wait for another one. If you have 4 EOF stacks and you enter a critical part of your code on one of them, 75% of your threads (and that means 75% of your users) won&#8217;t take the hit. The downside is more memory usage. You&#8217;ll have multiple copies of the row snapshots, plus all the objects needed to handle the database connection. And, of course, you may have to increase the number of maximum simultaneous connections on the database, which may force you to increase the maximum shared memory and semaphores on your operating system configuration. The good part is that, if you are using Wonder, creating the EOF stacks themselves is as simple as adding a property to your Properties file. That&#8217;s right! Just set er.extensions.ERXObjectStoreCoordinatorPool.maxCoordinators=x, being x the number of EOF stacks you want. That&#8217;s it, really. It just works, and it tries to minimize weirdness by creating all the editing contexts on a session in the same stack. It&#8217;s that good. It&#8217;s Wonder!</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/dr-optimistic-locking/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>drawImage performance on Leopard</title>
		<link>http://terminalapp.net/drawimage-performance-on-leopard/</link>
		<comments>http://terminalapp.net/drawimage-performance-on-leopard/#comments</comments>
		<pubDate>Wed, 27 Feb 2008 16:54:31 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/drawimage-performance-on-leopard/</guid>
		<description><![CDATA[A not very fast but handy way to downscale images in a WebObjects application is using Java 2D APIs, with code like this: BufferedImage reducedImage = new BufferedImage(newX, newY, BufferedImage.TYPE_INT_RGB); Graphics2D g = reducedImage.createGraphics(); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); &#8230; <a href="http://terminalapp.net/drawimage-performance-on-leopard/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A not very fast but handy way to downscale images in a WebObjects application is using Java 2D APIs, with code like this:</p>
<p><code><br />
BufferedImage reducedImage = new BufferedImage(newX, newY, BufferedImage.TYPE_INT_RGB);<br />
Graphics2D g = reducedImage.createGraphics();<br />
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);<br />
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);<br />
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);</p>
<p>g.drawImage(originalImage, 0, 0, newX, newY, 0, 0, originalImage.getWidth(), originalImage.getHeight(), null);<br />
g.dispose();<br />
</code></p>
<p>Although not blazing fast, this is enough for many applications. I could reduce a 7 Mega-Pixels image to something like 250 pixels wide in about one second, or less, in my PowerBook G4. But this was in Tiger.</p>
<p>In Leopard, as some of you may have noticed (and if you have applications deployed on Leopard Server, be aware) this is incredibly slow. When I say slow, I say five minutes, or even more, with the CPU being used at 100% during that time.</p>
<p>There are two reasons that lead to this. The first (which is not a problem in itself, but it&#8217;s a cause of the problem): Apple switched from Quartz to Sun2D graphics engine as the default one for Java applications on Leopard. So, all your image manipulation is being done using the Sun pipeline now. This would not be a problem, except for the second reason: <del datetime="2008-03-18T17:58:17+00:00">the Apple JVM implementation has a bug that is slowing Sun&#8217;s pipeline drawImage method to a crawl</del>. Actually, that was not the real reason. I testes this on FreeBSD (using Diablo JDK) and the speed was similar to Leopard&#8217;s. Sun2D is REALLY slow, to the point of being useless. I&#8217;m now using ImageMagick.</p>
<p>The only solution for now is forcing the application to use Quartz engine. You can do that using the command line option -Dapple.awt.graphics.UseQuartz=true. And, of course, <a href="http://bugreporter.apple.com">file a bug</a> on this!</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/drawimage-performance-on-leopard/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Avoid escaping URLs in Apache rewrite rules</title>
		<link>http://terminalapp.net/avoid-escaping-urls-in-apache-rewrite-rules/</link>
		<comments>http://terminalapp.net/avoid-escaping-urls-in-apache-rewrite-rules/#comments</comments>
		<pubDate>Thu, 24 Jan 2008 19:07:18 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[UNIX]]></category>
		<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/avoid-escaping-urls-in-apache-rewrite-rules/</guid>
		<description><![CDATA[Today we started hacking some Apache rewrite rules to make some URLs a little more friendly. All of the URLs we are rewriting are entry points for our application, which in the WO world means direct actions. All of them &#8230; <a href="http://terminalapp.net/avoid-escaping-urls-in-apache-rewrite-rules/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Today we started hacking some Apache rewrite rules to make some URLs a little more friendly. All of the URLs we are rewriting are entry points for our application, which in the WO world means direct actions.</p>
<p>All of them contain queries parts. These are the arguments in a URL, like http://domain.com/something?arg=value&#038;anotherArg=anotherValue. Well, everything was running fine until we accessed an URL with a escaped character. We had the following rule:</p>
<p><code><br />
RewriteRule ^/optOut(.*) /cgi-bin/WebObjects/OurApp.woa/wa/optOut$1 [R]<br />
</code></p>
<p>When we tried to access the URL http://domain.com/optOut?email=me%40domain.com, we got:</p>
<p><code></p>
<p>http://domain.mac/cgi-bin/WebObjects/OurApp.woa/wa/optOut?email=me%2540domain.com</p>
<p></code></p>
<p>Note the last part or the URL. The problem is that the original % in %40 (the escape code for @) was being itself escaped, leading to a corrupt URL. The result of calling formValueForKey on this was me%40domain.com.</p>
<p>After googling for a while, I found out many people have this problem, but surprisingly I could not find a decent solution. I saw hacks with escape internal functions and PHP weird variables that obviously wouldn&#8217;t help me at all, and I was starting to get nervous.</p>
<p>Well, while reading the <a href="http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html">rewrite module documentation</a>, I found the solution right there: the NE option. According to the docs:</p>
<blockquote><p>
&#8216;noescape|NE&#8217; (no URI escaping of output)<br />
This flag prevents mod_rewrite from applying the usual URI escaping rules to the result of a rewrite. Ordinarily, special characters (such as &#8216;%&#8217;, &#8216;$&#8217;, &#8216;;&#8217;, and so on) will be escaped into their hexcode equivalents (&#8216;%25&#8242;, &#8216;%24&#8242;, and &#8216;%3B&#8217;, respectively); this flag prevents this from happening. This allows percent symbols to appear in the output(&#8230;)
</p></blockquote>
<p>Well, this is it. I saw so many pages with people asking about this problem without getting any answers that I was not very confident on this, but I tried to change the rule for:</p>
<p><code><br />
RewriteRule ^/optOut(.*) /cgi-bin/WebObjects/OurApp.woa/wa/optOut$1 [R,NE]<br />
</code></p>
<p>And that&#8217;s it. It&#8217;s now working as it should, producing the correct URL:</p>
<p><code></p>
<p>http://domain.mac/cgi-bin/WebObjects/OurApp.woa/wa/optOut?email=me%40domain.com</p>
<p></code></p>
<p>Apparently, it&#8217;s that simple.</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/avoid-escaping-urls-in-apache-rewrite-rules/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A decent XML validator</title>
		<link>http://terminalapp.net/a-decent-xml-validator/</link>
		<comments>http://terminalapp.net/a-decent-xml-validator/#comments</comments>
		<pubDate>Sun, 20 Jan 2008 16:18:33 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/a-decent-xml-validator/</guid>
		<description><![CDATA[As written on all the good practice books about development, I write my applications ready for localization. To do that in WebObjects, one should put all the localizable strings in a strings file. In WebObjects applications, a strings file may &#8230; <a href="http://terminalapp.net/a-decent-xml-validator/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As written on all the good practice books about development, I write my applications ready for localization. To do that in WebObjects, one should put all the localizable strings in a strings file. In WebObjects applications, a strings file may be written in two formats: the Apple&#8217;s weird .plist format and XML. I use XML, because it looks more&#8230; well&#8230; I don&#8217;t really know, but I prefer it.</p>
<p>Anyway, some days ago I did a mistake in one of those files. I did something like: &lt;string&gt;Some String/string&gt;. As you can see, I forgot the &lt; character in the closing tag. When I run the application, all I got was this:</p>
<p><code><br />
The element type "string" must be terminated by the matching end-tag "</string>".: Parsing failed in line 1155, column 3<br />
</code></p>
<p>This is totally useless, as the line 1155 is actually the line before the last one in the file (the one that closes the &#8220;dict&#8221; entity). And yes, it&#8217;s a big file. Obviously, checking all the lines manually in undoable, even if I only checked the modified ones after the last commit (I added/changed many strings since then). So, the easiest way was to find a XML validator on the web, and hope it would point me the error.</p>
<p>How surprised I was when all the validators I found in the first two result pages pages of Googling for &#8220;XML Validator&#8221; reported exactly the same error as WebObjects itself. Great. Just great. And finally, I<a href="http://www.javaview.de/validator/"> found one validator that</a> saved the day. This guy, although a bit slow, showed me the exact line where the error was. So, <a href="http://www.javaview.de/validator/">bookmark this</a>. Really. It&#8217;s the <a href="http://www.javaview.de/validator/">best XML validator</a> around! And yes, just so that you don&#8217;t forget the link, let&#8217;s just <a href="http://www.javaview.de/validator/">mention it one more time</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/a-decent-xml-validator/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Profiling WebObjects applications</title>
		<link>http://terminalapp.net/profiling-webobjects-applications/</link>
		<comments>http://terminalapp.net/profiling-webobjects-applications/#comments</comments>
		<pubDate>Fri, 30 Nov 2007 14:49:58 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/profiling-webobjects-applications/</guid>
		<description><![CDATA[Recently I had to profile a WO application for memory leaks (more exactly, unintentional retention of objects that prevented them from being garbage-collected). Some quick notes: Eclipse TPTP will not work on Mac OS X. Period. Although Eclipse allows you to &#8230; <a href="http://terminalapp.net/profiling-webobjects-applications/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently I had to profile a WO application for memory leaks (more exactly, unintentional retention of objects that prevented them from being garbage-collected). Some quick notes:
<ul>
<li><a href="http://www.eclipse.org/tptp/">Eclipse TPTP</a> will not work on Mac OS X. Period. Although Eclipse allows you to install it without complaining, it does not work at all.</li>
<li>I found <a href="http://java.sun.com/j2se/1.5/pdf/jdk50_ts_guide.pdf">this nice article</a> about profiling and trouble-shooting in Java. Page 37 describes how to do what I initially wanted, although I didn&#8217;t need to get that far.</li>
<li>There are a lot of nice tools to help you peek inside the environment of your Java applications right there on your hard drive. I used jconsole. It&#8217;s really easy to use. First, add the -Dcom.sun.management.jmxremote VM option when launching the application. On Eclipse, this would be the &#8220;VM Arguments&#8221; in the &#8220;Arguments&#8221; tab of the Run Panel. Second, just open a terminal and write &#8220;jconsole&#8221;. Attach to the running app, and have fun.</li>
<li>Instruments (aka xRay) on Leopard has only one Java instrument, Java Threads. It appears to be almost useless on Java profiling. Yet another reason to stay on Tiger for now.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/profiling-webobjects-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Welcome to the Leopard WebObjects mess</title>
		<link>http://terminalapp.net/welcome-to-the-leopard-webobjects-mess/</link>
		<comments>http://terminalapp.net/welcome-to-the-leopard-webobjects-mess/#comments</comments>
		<pubDate>Tue, 30 Oct 2007 17:44:48 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/welcome-to-the-leopard-webobjects-mess/</guid>
		<description><![CDATA[So, you thought Leopard and WebObjects 5.4 would bring some good news to WebObjects developers, right? Well&#8230; so did I. I&#8217;m not even going to talk much about Leopard itself. It&#8217;s clearly an unfinished product, with dubious interface &#8220;improvements&#8221;, and &#8230; <a href="http://terminalapp.net/welcome-to-the-leopard-webobjects-mess/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>So, you thought Leopard and WebObjects 5.4 would bring some good news to WebObjects developers, right? Well&#8230; so did I.</p>
<p>I&#8217;m not even going to talk much about Leopard itself. It&#8217;s clearly an unfinished product, with <a href="http://arstechnica.com/reviews/os/mac-os-x-10-5.ars/4">dubious</a> <a href="http://arstechnica.com/reviews/os/mac-os-x-10-5.ars/13">interface &#8220;improvements&#8221;</a>, and totally unstable, at least on PowerPC macs. I try to keep my blog tecnhically-centered, and not based on personal opinions, but please Apple&#8230; you can do much better than that. Stop playing arround with the iPhone and concentrate on what really matters.</p>
<p>Well, about WO&#8230; Leopard has a new version of WebObjects, 5.4. It has <a href="http://lists.apple.com/archives/webobjects-dev//2007/Oct/msg00280.html">some bug fixes and improvements</a> over the previous versions, but unfortunately there are still a lot of show-stoppers that keep me from installing Leopard (and as you can guess from the last paragraph, I&#8217;m not specially motivated for that).</p>
<p>The first one is that <a href="http://sourceforge.net/projects/wonder">Wonder</a> still does not compile on 5.4. So, if you use Wonder (and you should), you must bring WebObjects 5.3 to Leopard. It&#8217;s not a very complicated process, but of course, it means trashing the brand new version. The good news is, if you use Wonder, you don&#8217;t really need WO 5.4, because almost all the features are already implemented on Wonder. The ideia is installing 5.4 (basically to get the Apache 2.2 adaptor), them trashing everything else, and finally installing 5.3. I installed it from the xCode 2 DMG and it worked fine. Anyway, Milke did an excellent (as always) <a href="http://lists.apple.com/archives/webobjects-dev//2007/Oct/msg00357.html">document about his trip back to 5.3 on Leopard</a>.</p>
<p>You should note the detail that the plists for LaunchD to boot WOTaskD and WOMonitor are not even in Leopard Client. Apparently, someone actually forgot to include that in the release. Assuming that most people develop without direct connect enabled (I don&#8217;t know how true this assumption is, but at least I do!), implying that they actually need WOTaskD to be running, it&#8217;s a bit scarry to see that actually no-one at apple tested this, or else they would find out that the files were not included. It surely doesn&#8217;t boost my confidance on all this.</p>
<p>Also, I develop using virtual hosts. Basically I set the adaptor URL, in WOLips launch options, to be something like http://aVirtualHost.mac/cgi-bin/WebObjects. I kept getting the &#8220;No instance available&#8221; message until I run &#8220;sudo hostname -s aVirtualHost.mac&#8221; on the command line and restarted every WO-related process (apache, WOTaskD, and the app itself). BTW, note that the file included in apache2 configuration for vhost configuration has errors, and will actually kill apache at launch if you don&#8217;t remove both examples that come with it (the error is in the logging configuration for both sample virtual hosts). Even worse, if you are trying to look for apache error logs in the error_log apache file as you always did on tiger&#8230; forget it. This kind of errors are now thrown to /var/log/system.log.</p>
<p><del datetime="2007-10-31T00:05:50+00:00">But the biggest show-stopper is <a href="http://www.rubicode.com/Software/EOGenerator/">EOGenerator</a>. You <em>do</em> use EOgenerator, don&#8217;t you? EOGenerator was based on the same frameworks as the Apple WO tools, like EOModeler. Apple moved those frameworks from &#8220;deprecated&#8221; to &#8220;dead&#8221; with Leopard, so <a href="http://lists.apple.com/archives/webobjects-dev//2007/Oct/msg00459.html">EOGenerator went to the grave</a> with them. Relax, there will be a Java replacement included on WOLips, but it&#8217;s still not there.</del> Well, talk about living in the information age&#8230; <a href="http://lists.apple.com/archives/webobjects-dev//2007/Oct/msg00517.html">the EOGenerator is out</a>! :)</p>
<p>So, if you are an WebObjects developer wondering about jumping to Leopard&#8230; my adviced is, wait. Unless you don&#8217;t use Wonder and EOGenerator, which is highly unlikely.</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/welcome-to-the-leopard-webobjects-mess/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Recovering from optimistic locking exceptions</title>
		<link>http://terminalapp.net/recovering-from-optimistic-locking-exceptions/</link>
		<comments>http://terminalapp.net/recovering-from-optimistic-locking-exceptions/#comments</comments>
		<pubDate>Sat, 18 Aug 2007 00:44:57 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/recovering-from-optimistic-locking-exceptions/</guid>
		<description><![CDATA[WARNING: the solution presented in this article is wrong. It&#8217;s a partial solution only, it won&#8217;t always work, and you may screw up your data. To see why, check my second article on this issue. There are many situations, in &#8230; <a href="http://terminalapp.net/recovering-from-optimistic-locking-exceptions/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[</p>
<div style="background: #fdd; border-color: #f00; border-style: solid;">
<p style="padding: 5px;"><strong>WARNING:</strong> the solution presented in this article is wrong. It&#8217;s a partial solution only, it won&#8217;t always work, and you may screw up your data. To see why, check <a href="http://terminalapp.net/dr-optimistic-locking/">my second article</a> on this issue.</p>
</div>
<p>There are many situations, in simple web applications, where you don&#8217;t really have to deal with concurrent data update. Imagine you are writing a blog app, like WordPress. Even if two persons are changing a post title at the same time (which, by it&#8217;s nature, it&#8217;s a really rare event), you, as the developer, may simply don&#8217;t care about it, and rely on the &#8220;last write wins&#8221; strategy.</p>
<p>When you are writing more complex stuff, specially when one needs to have really complex data being modified by different users, in different situations, at the same time, and when you have pre-calculated data, because grabbing all the objects and calculating the results in real time (fast enough for a page load) is simply not possible, you will have serious headaches (it&#8217;s already hard enough to understand this sentence without re-reading it!).</p>
<p>When developing WebObjects, there are two main classes of concurrency problems to solve. Intra-instance concurrent data updates, and inter-instance concurrent updates. It would appear that the second is much harder than the first&#8230; well&#8230; it&#8217;s not.</p>
<p>Intra-instance updates should be simplified by automatic data merging between contexts. But there are some problems. The biggest problem is that, in fact, it&#8217;s possible to totally overwrite a data modification done by another user without getting any notification of that at all. How? <a href="http://lists.apple.com/archives/webobjects-dev/2007/Jul/msg00680.html">See this thread</a> on the WebObjects Dev mailing list. The biggest problem is that, while a context is locked, data merging simply does not occur. So, imagine you lock context A and start modifying data. At the same time, someone locks context B on another thread, changes the same data that you are modifying in context A, and saves it. The data you changed is merged on all the other contexts where the same objects are present, as long as they are unlocked. But remember, your context A isn&#8217;t, so no merging will occur for now. Now, imagine you continue working on context A, and finally save it, and unlock it. The merging will occur now &#8211; to late, because you already saved, and probably won&#8217;t work any more in that context.</p>
<p>By now, you say &#8220;Naaah, that won&#8217;t happen, because WebObjects will trigger an optimistic locking exception&#8221;. No it won&#8217;t. Why? Remember that context B saved while context A was locked, right? So, when B saves, the row snapshots of the EOF stack will be updated. When you save context A, assuming that no one else (besided the A and B guys) worked on the same data at the same time, EOF will base the OL check on the row snapshots that is has in the stack. Remember, this are no more the snapshots for objects in context A. They are the snapshots caused by B saving, and those will be the same that exist in the DB. So, no OL exception will occur. Congratulations, A just trashed B data updates, and wasn&#8217;t notified at all.</p>
<p>Are you already scared? Good. So be even more scared. There are only two solutions for this. The first one, create a lot of separate EOF stacks (one per session, assuming the sessions are being locked in the normal WO way). This sucks, because it&#8217;s too resource expensive. It will use a lot of memory (lots or repeated snapshots in memory) and it will open many connections to the DB, that may be a problem by itself. The second solution&#8230; classic Java locking (syncronized keyword, etc). This is the time you start thinking about being a farmer, right?</p>
<p>Well, the news on inter-instance concurrency are better, although far from perfect. Here, there&#8217;s no data merging, and no Java syncronized stuff. Everything will be based in locking. Usually optimistic locking, but you can also use pessimistic locking (ie, &#8220;real&#8221; row-database locking). Pessimistic locking has huge problems and many experienced coders will recommend that you stay away from it. So I will not cover that, and I&#8217;ll assume you want to use Optimistic locking.</p>
<p>The ideia is simple: create context, fetch data, modify data, save. If you get a locking exception, re-fetch data, re-modify, and re-try to save it until no OL exception is thrown.</p>
<p>This is simple for simple stuff, ie, when you have one single object causing the failure. Now imagine the following scenario (and this isn&#8217;t imaginary, it occured to me): you are working with dozens of objects thay may cause OL exceptions, and if one of them causes it, all the others will probably cause too. Also, I need to create some objects (relationships, mostly, but also some individual objects) depending on what I&#8217;m doing. If I get an OL exception, I must go back, delete those objects, and create new ones, because the fact that I create, or not, an specific object depends on the data already present on the data storage. In theory, this will not be a problem: create context, fetch data, modify data, create objects (and save the created objects in a temporary array), save, get OL exception, delete all the created objects, re-fetch data, re-modify data, re-create objects, save. Right? Wrong. Unfortunately I&#8217;ve hit some obscure WebObejcts bug, as you can see in <a href="http://lists.apple.com/archives/webobjects-dev/2007/Aug/msg00272.html">this WODev thread</a>. This is the time you start browsing the net looking for a farm to buy, if you don&#8217;t already have one.</p>
<p>After a lot of experiencies, I think I have reached a reasonable way to handle this in a simple manner (remember, you will always have to think about intra-instance problems, but we are dealing with inter-instance now). Instead of fighting with WO about deleting created objects, and getting outdated data when one was supposed to get fresh one, simply don&#8217;t worry about it, and create everything from scratch every time you try to save. The code will look something like this:</p>
<pre>
synchronized (lock) { // Solving intra-instance problems,
                      //your millage may vary on this, of course
  int tries = 0;

  // Make MAX_SAVE_ANSWERS_TRY_COUNT something reasonable, like 50
  while( tries < MAX_SAVE_ANSWERS_TRY_COUNT ) { 

    // Setup context
    EOEditingContext context = new EOEditingContext();
    context.setFetchTimestamp(System.currentTimeMillis());

    // Make sure nothing "strange" will happen, this is a simply delegate
    // that blocks merging. Probably it won't be needed but I'm paranoid.
    context.setDelegate(new NoMergingECDeletage());

    // Register the EC in my session lock manager, to handle locking and
    // garbage collection automatically. Your millage may vary, specially
    // if using Wonder in a smarter way than I do.
    session.lockManager().registerEditingContext(context); 

    // Get local copies of objects
    < here you get all the local copies of your objects. Remember the
    context.setFetchTimestamp(System.currentTimeMillis()); line above?
    This will guarantee that ALL the objects you get in this context will
    contain fresh data. You can use EOUtilities.localInstanceOfObject,
    walking trough relationships like object.otherObject().anotherOne(),
    using fetch specifications, whatever. Everything will be fresh. >

    // Let's do it.
    < Do your thing here. Create objects, modify objects, delete objects,
    go crazy. >

    // Try to save
    try {
      context.saveChanges();
      return;
    } catch (EOGeneralAdaptorException saveException) {
      ++tries;

      // isOptimisticLockingFailure is basically the method
      // with the same name in Apple docs
      if( Util.isOptimisticLockingFailure(saveException) ) {

        NSLog.out.appendln("Optimistic locking exception");
        // Note that I don't refault anything here. I don't need it.
        // On the next iteration, a new EC will be created, and all
        // the objects will be automatically refaulted.
      } else {
        // It's some other exception, handle it somewhere else
        throw saveException;
      }
    }
  }

  throw new RunTimeException("Could not save after " +
MAX_SAVE_ANSWERS_TRY_COUNT + " tries. Help me.");
}
</pre>
<p>At the beggining, I didn&#8217;t like this approach at all. But after using in some places, and seeing it work perfectly, I&#8217;m liking it more and more. The main advantage is, it works. No strange problems, no fighting with WO bugs, no strange refaulting behaviour. It&#8217;s a dream come true. It just works. But, of course, it has some disadvantages. All the objects are fetched from the data store, with the consequent performance hit. So, if you are dealing with many many objects, this may be undoable for you. Also, it has a more serious problem if you are lazy like me: you cannot have an object binded to the page component, and use it in the processing. The reason is that you need to bring that object &#8220;inside&#8221; the newly created EC, and localInstanceOfObject won&#8217;t copy the unsaved modifications, and will not even copy newly created objects. So you have to manually copy and reproduce all the user modifications to the local copies of objects. More work for you, more work for the CPU, more objects in memory. It&#8217;s life.</p>
<p>Written at the beautiful and peaceful town of <a href="http://en.wikipedia.org/wiki/Serpa">Serpa</a>. Not on an iPhone.</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/recovering-from-optimistic-locking-exceptions/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WebObjects survey</title>
		<link>http://terminalapp.net/webobjects-survey/</link>
		<comments>http://terminalapp.net/webobjects-survey/#comments</comments>
		<pubDate>Fri, 29 Jun 2007 14:31:14 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/webobjects-survey/</guid>
		<description><![CDATA[Pascal Robert has just setup an online survey for WebObjects developers. The survey is short and direct2thePoint :) so you won&#8217;t spend more than 5 minutes on it. The results will be delivered to Apple, to help them focus their &#8230; <a href="http://terminalapp.net/webobjects-survey/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Pascal Robert has just setup an <a href="http://www.surveymonkey.com/s.aspx?sm=Rd8PBbh0xxJh3eyuPPvdIg_3d_3d">online survey</a> for WebObjects developers. The survey is short and direct2thePoint :) so you won&#8217;t spend more than 5 minutes on it. The results will be delivered to Apple, to help them focus their development resources on the needs of the community. As Pascal said, the rules are:</p>
<ul>
<li>- One survey per organization, if I see the same organization more than one time, I will delete the duplicates</li>
<li>- Please, please, be honest in your answers</li>
</ul>
<p>So, if you are an WebObjects developer, <a href="http://www.surveymonkey.com/s.aspx?sm=Rd8PBbh0xxJh3eyuPPvdIg_3d_3d">take the survey now</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/webobjects-survey/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>svgobjects 2.0</title>
		<link>http://terminalapp.net/svgobjects-20/</link>
		<comments>http://terminalapp.net/svgobjects-20/#comments</comments>
		<pubDate>Mon, 25 Jun 2007 21:36:42 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/svgobjects-20/</guid>
		<description><![CDATA[As you may know, Safari 3.0 finally fully supports SVGs. Based on that, Ravi Mendis released the first beta of svgobjects 2.0, an SVG framework for WebObjects. Apparently, the framework started with the goal of drawing charts dynamically, but the &#8230; <a href="http://terminalapp.net/svgobjects-20/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As you may know, Safari 3.0 finally fully supports SVGs. Based on that, Ravi Mendis released the first beta of <a href="http://www.svgobjects2.com/SVGObjects2/SVGObjects.html">svgobjects 2.0</a>, an SVG framework for WebObjects. Apparently, the framework started with the goal of drawing charts dynamically, but the author extended it to support the drawing of full-screen interfaces that could be used on the desktop and, even more, on mobile devices, like the iPhone. It may become a very useful framework for building iPhone-targeted web apps!</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/svgobjects-20/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WebObjects rocks</title>
		<link>http://terminalapp.net/webobjects-rocks/</link>
		<comments>http://terminalapp.net/webobjects-rocks/#comments</comments>
		<pubDate>Fri, 15 Jun 2007 23:54:46 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/webobjects-rocks/</guid>
		<description><![CDATA[Well, WWDC is almost done, I&#8217;m waiting for the last session on Level 3 of Moscone, near one of these really big windows. It&#8217;s a really big pain to not being able to write here all that I have learned &#8230; <a href="http://terminalapp.net/webobjects-rocks/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Well, WWDC is almost done, I&#8217;m waiting for the last session on Level 3 of Moscone, near one of these really big windows.</p>
<p>It&#8217;s a really big pain to not being able to write here all that I have learned about WebObjects (for those of you who don&#8217;t know, WWDC sessions are covered by NDAs).</p>
<p>Someone asked on the WebObjects mailing list how do we classify the WO news, from A to C. Well, I can say, A++++! I think the future of WebObjects will be susprising. Apple showed us some stuff that, in my opinion, is probably almost as revolutionary as the original WebObjects framework itself. But we still will have to wait.</p>
<p>The only thing I can say more is: if you are (considering) doing web application development, don&#8217;t be stupid &#8211; learn WebObjects NOW. Currently, it&#8217;s the most powerful web application development environment by far. And in some future time this advantage will be an order of magnitude higher.</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/webobjects-rocks/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>W(O)W(O)DC 2007</title>
		<link>http://terminalapp.net/wowodc-2007/</link>
		<comments>http://terminalapp.net/wowodc-2007/#comments</comments>
		<pubDate>Wed, 06 Jun 2007 18:47:14 +0000</pubDate>
		<dc:creator>Miguel Arroz</dc:creator>
				<category><![CDATA[WebObjects]]></category>

		<guid isPermaLink="false">http://terminalapp.net/wowodc-2007/</guid>
		<description><![CDATA[I&#8217;ll go tomorrow to SF, to assist WOWODC 2007 and WWDC 2007, so I won&#8217;t post here for some time. WOWODC was organized by Pascal Robert, as a result of the lack of support Apple gives to WebObjects developers, and &#8230; <a href="http://terminalapp.net/wowodc-2007/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll go tomorrow to SF, to assist <a href="http://www.gvcsitemaker.com/wowodc.2007/home">WOWODC 2007</a> and <a href="http://developer.apple.com/wwdc/">WWDC 2007</a>, so I won&#8217;t post here for some time.</p>
<p>WOWODC was organized by Pascal Robert, as a result of the lack of support Apple gives to WebObjects developers, and will feature some well-known people in the WebObjects community, like Chuck Hill, Mike Schrag or Anjo Krank, who we will certainly flood with questions. Mr. Pierre Frisch, the WebObjects Product Manager at Apple will be there too. This will be a great year for WebObjects, as it&#8217;s community will provide the attention it deserves! :)</p>
<p>See you in two weeks.</p>
]]></content:encoded>
			<wfw:commentRss>http://terminalapp.net/wowodc-2007/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

